1254885Sdumbbell/* 2254885Sdumbbell * Copyright 2007-8 Advanced Micro Devices, Inc. 3254885Sdumbbell * Copyright 2008 Red Hat Inc. 4254885Sdumbbell * 5254885Sdumbbell * Permission is hereby granted, free of charge, to any person obtaining a 6254885Sdumbbell * copy of this software and associated documentation files (the "Software"), 7254885Sdumbbell * to deal in the Software without restriction, including without limitation 8254885Sdumbbell * the rights to use, copy, modify, merge, publish, distribute, sublicense, 9254885Sdumbbell * and/or sell copies of the Software, and to permit persons to whom the 10254885Sdumbbell * Software is furnished to do so, subject to the following conditions: 11254885Sdumbbell * 12254885Sdumbbell * The above copyright notice and this permission notice shall be included in 13254885Sdumbbell * all copies or substantial portions of the Software. 14254885Sdumbbell * 15254885Sdumbbell * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 16254885Sdumbbell * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 17254885Sdumbbell * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL 18254885Sdumbbell * THE COPYRIGHT HOLDER(S) OR AUTHOR(S) BE LIABLE FOR ANY CLAIM, DAMAGES OR 19254885Sdumbbell * OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, 20254885Sdumbbell * ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR 21254885Sdumbbell * OTHER DEALINGS IN THE SOFTWARE. 22254885Sdumbbell * 23254885Sdumbbell * Authors: Dave Airlie 24254885Sdumbbell * Alex Deucher 25254885Sdumbbell */ 26254885Sdumbbell 27254885Sdumbbell#include <sys/cdefs.h> 28254885Sdumbbell__FBSDID("$FreeBSD$"); 29254885Sdumbbell 30254885Sdumbbell#include <dev/drm2/drmP.h> 31254885Sdumbbell#include <dev/drm2/drm_crtc_helper.h> 32254885Sdumbbell#include <dev/drm2/radeon/radeon_drm.h> 33254885Sdumbbell#include "radeon.h" 34254885Sdumbbell#include "atom.h" 35254885Sdumbbell 36254885Sdumbbell 37254885Sdumbbellstatic uint32_t radeon_encoder_clones(struct drm_encoder *encoder) 38254885Sdumbbell{ 39254885Sdumbbell struct drm_device *dev = encoder->dev; 40254885Sdumbbell struct radeon_device *rdev = dev->dev_private; 41254885Sdumbbell struct radeon_encoder *radeon_encoder = to_radeon_encoder(encoder); 42254885Sdumbbell struct drm_encoder *clone_encoder; 43254885Sdumbbell uint32_t index_mask = 0; 44254885Sdumbbell int count; 45254885Sdumbbell 46254885Sdumbbell /* DIG routing gets problematic */ 47254885Sdumbbell if (rdev->family >= CHIP_R600) 48254885Sdumbbell return index_mask; 49254885Sdumbbell /* LVDS/TV are too wacky */ 50254885Sdumbbell if (radeon_encoder->devices & ATOM_DEVICE_LCD_SUPPORT) 51254885Sdumbbell return index_mask; 52254885Sdumbbell /* DVO requires 2x ppll clocks depending on tmds chip */ 53254885Sdumbbell if (radeon_encoder->devices & ATOM_DEVICE_DFP2_SUPPORT) 54254885Sdumbbell return index_mask; 55254885Sdumbbell 56254885Sdumbbell count = -1; 57254885Sdumbbell list_for_each_entry(clone_encoder, &dev->mode_config.encoder_list, head) { 58254885Sdumbbell struct radeon_encoder *radeon_clone = to_radeon_encoder(clone_encoder); 59254885Sdumbbell count++; 60254885Sdumbbell 61254885Sdumbbell if (clone_encoder == encoder) 62254885Sdumbbell continue; 63254885Sdumbbell if (radeon_clone->devices & (ATOM_DEVICE_LCD_SUPPORT)) 64254885Sdumbbell continue; 65254885Sdumbbell if (radeon_clone->devices & ATOM_DEVICE_DFP2_SUPPORT) 66254885Sdumbbell continue; 67254885Sdumbbell else 68254885Sdumbbell index_mask |= (1 << count); 69254885Sdumbbell } 70254885Sdumbbell return index_mask; 71254885Sdumbbell} 72254885Sdumbbell 73254885Sdumbbellvoid radeon_setup_encoder_clones(struct drm_device *dev) 74254885Sdumbbell{ 75254885Sdumbbell struct drm_encoder *encoder; 76254885Sdumbbell 77254885Sdumbbell list_for_each_entry(encoder, &dev->mode_config.encoder_list, head) { 78254885Sdumbbell encoder->possible_clones = radeon_encoder_clones(encoder); 79254885Sdumbbell } 80254885Sdumbbell} 81254885Sdumbbell 82254885Sdumbbelluint32_t 83254885Sdumbbellradeon_get_encoder_enum(struct drm_device *dev, uint32_t supported_device, uint8_t dac) 84254885Sdumbbell{ 85254885Sdumbbell struct radeon_device *rdev = dev->dev_private; 86254885Sdumbbell uint32_t ret = 0; 87254885Sdumbbell 88254885Sdumbbell switch (supported_device) { 89254885Sdumbbell case ATOM_DEVICE_CRT1_SUPPORT: 90254885Sdumbbell case ATOM_DEVICE_TV1_SUPPORT: 91254885Sdumbbell case ATOM_DEVICE_TV2_SUPPORT: 92254885Sdumbbell case ATOM_DEVICE_CRT2_SUPPORT: 93254885Sdumbbell case ATOM_DEVICE_CV_SUPPORT: 94254885Sdumbbell switch (dac) { 95254885Sdumbbell case 1: /* dac a */ 96254885Sdumbbell if ((rdev->family == CHIP_RS300) || 97254885Sdumbbell (rdev->family == CHIP_RS400) || 98254885Sdumbbell (rdev->family == CHIP_RS480)) 99254885Sdumbbell ret = ENCODER_INTERNAL_DAC2_ENUM_ID1; 100254885Sdumbbell else if (ASIC_IS_AVIVO(rdev)) 101254885Sdumbbell ret = ENCODER_INTERNAL_KLDSCP_DAC1_ENUM_ID1; 102254885Sdumbbell else 103254885Sdumbbell ret = ENCODER_INTERNAL_DAC1_ENUM_ID1; 104254885Sdumbbell break; 105254885Sdumbbell case 2: /* dac b */ 106254885Sdumbbell if (ASIC_IS_AVIVO(rdev)) 107254885Sdumbbell ret = ENCODER_INTERNAL_KLDSCP_DAC2_ENUM_ID1; 108254885Sdumbbell else { 109254885Sdumbbell /*if (rdev->family == CHIP_R200) 110254885Sdumbbell ret = ENCODER_INTERNAL_DVO1_ENUM_ID1; 111254885Sdumbbell else*/ 112254885Sdumbbell ret = ENCODER_INTERNAL_DAC2_ENUM_ID1; 113254885Sdumbbell } 114254885Sdumbbell break; 115254885Sdumbbell case 3: /* external dac */ 116254885Sdumbbell if (ASIC_IS_AVIVO(rdev)) 117254885Sdumbbell ret = ENCODER_INTERNAL_KLDSCP_DVO1_ENUM_ID1; 118254885Sdumbbell else 119254885Sdumbbell ret = ENCODER_INTERNAL_DVO1_ENUM_ID1; 120254885Sdumbbell break; 121254885Sdumbbell } 122254885Sdumbbell break; 123254885Sdumbbell case ATOM_DEVICE_LCD1_SUPPORT: 124254885Sdumbbell if (ASIC_IS_AVIVO(rdev)) 125254885Sdumbbell ret = ENCODER_INTERNAL_LVTM1_ENUM_ID1; 126254885Sdumbbell else 127254885Sdumbbell ret = ENCODER_INTERNAL_LVDS_ENUM_ID1; 128254885Sdumbbell break; 129254885Sdumbbell case ATOM_DEVICE_DFP1_SUPPORT: 130254885Sdumbbell if ((rdev->family == CHIP_RS300) || 131254885Sdumbbell (rdev->family == CHIP_RS400) || 132254885Sdumbbell (rdev->family == CHIP_RS480)) 133254885Sdumbbell ret = ENCODER_INTERNAL_DVO1_ENUM_ID1; 134254885Sdumbbell else if (ASIC_IS_AVIVO(rdev)) 135254885Sdumbbell ret = ENCODER_INTERNAL_KLDSCP_TMDS1_ENUM_ID1; 136254885Sdumbbell else 137254885Sdumbbell ret = ENCODER_INTERNAL_TMDS1_ENUM_ID1; 138254885Sdumbbell break; 139254885Sdumbbell case ATOM_DEVICE_LCD2_SUPPORT: 140254885Sdumbbell case ATOM_DEVICE_DFP2_SUPPORT: 141254885Sdumbbell if ((rdev->family == CHIP_RS600) || 142254885Sdumbbell (rdev->family == CHIP_RS690) || 143254885Sdumbbell (rdev->family == CHIP_RS740)) 144254885Sdumbbell ret = ENCODER_INTERNAL_DDI_ENUM_ID1; 145254885Sdumbbell else if (ASIC_IS_AVIVO(rdev)) 146254885Sdumbbell ret = ENCODER_INTERNAL_KLDSCP_DVO1_ENUM_ID1; 147254885Sdumbbell else 148254885Sdumbbell ret = ENCODER_INTERNAL_DVO1_ENUM_ID1; 149254885Sdumbbell break; 150254885Sdumbbell case ATOM_DEVICE_DFP3_SUPPORT: 151254885Sdumbbell ret = ENCODER_INTERNAL_LVTM1_ENUM_ID1; 152254885Sdumbbell break; 153254885Sdumbbell } 154254885Sdumbbell 155254885Sdumbbell return ret; 156254885Sdumbbell} 157254885Sdumbbell 158254885Sdumbbellvoid 159254885Sdumbbellradeon_link_encoder_connector(struct drm_device *dev) 160254885Sdumbbell{ 161254885Sdumbbell struct radeon_device *rdev = dev->dev_private; 162254885Sdumbbell struct drm_connector *connector; 163254885Sdumbbell struct radeon_connector *radeon_connector; 164254885Sdumbbell struct drm_encoder *encoder; 165254885Sdumbbell struct radeon_encoder *radeon_encoder; 166254885Sdumbbell 167254885Sdumbbell /* walk the list and link encoders to connectors */ 168254885Sdumbbell list_for_each_entry(connector, &dev->mode_config.connector_list, head) { 169254885Sdumbbell radeon_connector = to_radeon_connector(connector); 170254885Sdumbbell list_for_each_entry(encoder, &dev->mode_config.encoder_list, head) { 171254885Sdumbbell radeon_encoder = to_radeon_encoder(encoder); 172254885Sdumbbell if (radeon_encoder->devices & radeon_connector->devices) { 173254885Sdumbbell drm_mode_connector_attach_encoder(connector, encoder); 174254885Sdumbbell if (radeon_encoder->devices & (ATOM_DEVICE_LCD_SUPPORT)) { 175254885Sdumbbell if (rdev->is_atom_bios) 176254885Sdumbbell radeon_atom_backlight_init(radeon_encoder, connector); 177254885Sdumbbell else 178254885Sdumbbell radeon_legacy_backlight_init(radeon_encoder, connector); 179254885Sdumbbell rdev->mode_info.bl_encoder = radeon_encoder; 180254885Sdumbbell } 181254885Sdumbbell } 182254885Sdumbbell } 183254885Sdumbbell } 184254885Sdumbbell} 185254885Sdumbbell 186254885Sdumbbellvoid radeon_encoder_set_active_device(struct drm_encoder *encoder) 187254885Sdumbbell{ 188254885Sdumbbell struct drm_device *dev = encoder->dev; 189254885Sdumbbell struct radeon_encoder *radeon_encoder = to_radeon_encoder(encoder); 190254885Sdumbbell struct drm_connector *connector; 191254885Sdumbbell 192254885Sdumbbell list_for_each_entry(connector, &dev->mode_config.connector_list, head) { 193254885Sdumbbell if (connector->encoder == encoder) { 194254885Sdumbbell struct radeon_connector *radeon_connector = to_radeon_connector(connector); 195254885Sdumbbell radeon_encoder->active_device = radeon_encoder->devices & radeon_connector->devices; 196254885Sdumbbell DRM_DEBUG_KMS("setting active device to %08x from %08x %08x for encoder %d\n", 197254885Sdumbbell radeon_encoder->active_device, radeon_encoder->devices, 198254885Sdumbbell radeon_connector->devices, encoder->encoder_type); 199254885Sdumbbell } 200254885Sdumbbell } 201254885Sdumbbell} 202254885Sdumbbell 203254885Sdumbbellstruct drm_connector * 204254885Sdumbbellradeon_get_connector_for_encoder(struct drm_encoder *encoder) 205254885Sdumbbell{ 206254885Sdumbbell struct drm_device *dev = encoder->dev; 207254885Sdumbbell struct radeon_encoder *radeon_encoder = to_radeon_encoder(encoder); 208254885Sdumbbell struct drm_connector *connector; 209254885Sdumbbell struct radeon_connector *radeon_connector; 210254885Sdumbbell 211254885Sdumbbell list_for_each_entry(connector, &dev->mode_config.connector_list, head) { 212254885Sdumbbell radeon_connector = to_radeon_connector(connector); 213254885Sdumbbell if (radeon_encoder->active_device & radeon_connector->devices) 214254885Sdumbbell return connector; 215254885Sdumbbell } 216254885Sdumbbell return NULL; 217254885Sdumbbell} 218254885Sdumbbell 219254885Sdumbbellstruct drm_connector * 220254885Sdumbbellradeon_get_connector_for_encoder_init(struct drm_encoder *encoder) 221254885Sdumbbell{ 222254885Sdumbbell struct drm_device *dev = encoder->dev; 223254885Sdumbbell struct radeon_encoder *radeon_encoder = to_radeon_encoder(encoder); 224254885Sdumbbell struct drm_connector *connector; 225254885Sdumbbell struct radeon_connector *radeon_connector; 226254885Sdumbbell 227254885Sdumbbell list_for_each_entry(connector, &dev->mode_config.connector_list, head) { 228254885Sdumbbell radeon_connector = to_radeon_connector(connector); 229254885Sdumbbell if (radeon_encoder->devices & radeon_connector->devices) 230254885Sdumbbell return connector; 231254885Sdumbbell } 232254885Sdumbbell return NULL; 233254885Sdumbbell} 234254885Sdumbbell 235254885Sdumbbellstruct drm_encoder *radeon_get_external_encoder(struct drm_encoder *encoder) 236254885Sdumbbell{ 237254885Sdumbbell struct drm_device *dev = encoder->dev; 238254885Sdumbbell struct radeon_encoder *radeon_encoder = to_radeon_encoder(encoder); 239254885Sdumbbell struct drm_encoder *other_encoder; 240254885Sdumbbell struct radeon_encoder *other_radeon_encoder; 241254885Sdumbbell 242254885Sdumbbell if (radeon_encoder->is_ext_encoder) 243254885Sdumbbell return NULL; 244254885Sdumbbell 245254885Sdumbbell list_for_each_entry(other_encoder, &dev->mode_config.encoder_list, head) { 246254885Sdumbbell if (other_encoder == encoder) 247254885Sdumbbell continue; 248254885Sdumbbell other_radeon_encoder = to_radeon_encoder(other_encoder); 249254885Sdumbbell if (other_radeon_encoder->is_ext_encoder && 250254885Sdumbbell (radeon_encoder->devices & other_radeon_encoder->devices)) 251254885Sdumbbell return other_encoder; 252254885Sdumbbell } 253254885Sdumbbell return NULL; 254254885Sdumbbell} 255254885Sdumbbell 256254885Sdumbbellu16 radeon_encoder_get_dp_bridge_encoder_id(struct drm_encoder *encoder) 257254885Sdumbbell{ 258254885Sdumbbell struct drm_encoder *other_encoder = radeon_get_external_encoder(encoder); 259254885Sdumbbell 260254885Sdumbbell if (other_encoder) { 261254885Sdumbbell struct radeon_encoder *radeon_encoder = to_radeon_encoder(other_encoder); 262254885Sdumbbell 263254885Sdumbbell switch (radeon_encoder->encoder_id) { 264254885Sdumbbell case ENCODER_OBJECT_ID_TRAVIS: 265254885Sdumbbell case ENCODER_OBJECT_ID_NUTMEG: 266254885Sdumbbell return radeon_encoder->encoder_id; 267254885Sdumbbell default: 268254885Sdumbbell return ENCODER_OBJECT_ID_NONE; 269254885Sdumbbell } 270254885Sdumbbell } 271254885Sdumbbell return ENCODER_OBJECT_ID_NONE; 272254885Sdumbbell} 273254885Sdumbbell 274254885Sdumbbellvoid radeon_panel_mode_fixup(struct drm_encoder *encoder, 275254885Sdumbbell struct drm_display_mode *adjusted_mode) 276254885Sdumbbell{ 277254885Sdumbbell struct radeon_encoder *radeon_encoder = to_radeon_encoder(encoder); 278254885Sdumbbell struct drm_device *dev = encoder->dev; 279254885Sdumbbell struct radeon_device *rdev = dev->dev_private; 280254885Sdumbbell struct drm_display_mode *native_mode = &radeon_encoder->native_mode; 281254885Sdumbbell unsigned hblank = native_mode->htotal - native_mode->hdisplay; 282254885Sdumbbell unsigned vblank = native_mode->vtotal - native_mode->vdisplay; 283254885Sdumbbell unsigned hover = native_mode->hsync_start - native_mode->hdisplay; 284254885Sdumbbell unsigned vover = native_mode->vsync_start - native_mode->vdisplay; 285254885Sdumbbell unsigned hsync_width = native_mode->hsync_end - native_mode->hsync_start; 286254885Sdumbbell unsigned vsync_width = native_mode->vsync_end - native_mode->vsync_start; 287254885Sdumbbell 288254885Sdumbbell adjusted_mode->clock = native_mode->clock; 289254885Sdumbbell adjusted_mode->flags = native_mode->flags; 290254885Sdumbbell 291254885Sdumbbell if (ASIC_IS_AVIVO(rdev)) { 292254885Sdumbbell adjusted_mode->hdisplay = native_mode->hdisplay; 293254885Sdumbbell adjusted_mode->vdisplay = native_mode->vdisplay; 294254885Sdumbbell } 295254885Sdumbbell 296254885Sdumbbell adjusted_mode->htotal = native_mode->hdisplay + hblank; 297254885Sdumbbell adjusted_mode->hsync_start = native_mode->hdisplay + hover; 298254885Sdumbbell adjusted_mode->hsync_end = adjusted_mode->hsync_start + hsync_width; 299254885Sdumbbell 300254885Sdumbbell adjusted_mode->vtotal = native_mode->vdisplay + vblank; 301254885Sdumbbell adjusted_mode->vsync_start = native_mode->vdisplay + vover; 302254885Sdumbbell adjusted_mode->vsync_end = adjusted_mode->vsync_start + vsync_width; 303254885Sdumbbell 304254885Sdumbbell drm_mode_set_crtcinfo(adjusted_mode, CRTC_INTERLACE_HALVE_V); 305254885Sdumbbell 306254885Sdumbbell if (ASIC_IS_AVIVO(rdev)) { 307254885Sdumbbell adjusted_mode->crtc_hdisplay = native_mode->hdisplay; 308254885Sdumbbell adjusted_mode->crtc_vdisplay = native_mode->vdisplay; 309254885Sdumbbell } 310254885Sdumbbell 311254885Sdumbbell adjusted_mode->crtc_htotal = adjusted_mode->crtc_hdisplay + hblank; 312254885Sdumbbell adjusted_mode->crtc_hsync_start = adjusted_mode->crtc_hdisplay + hover; 313254885Sdumbbell adjusted_mode->crtc_hsync_end = adjusted_mode->crtc_hsync_start + hsync_width; 314254885Sdumbbell 315254885Sdumbbell adjusted_mode->crtc_vtotal = adjusted_mode->crtc_vdisplay + vblank; 316254885Sdumbbell adjusted_mode->crtc_vsync_start = adjusted_mode->crtc_vdisplay + vover; 317254885Sdumbbell adjusted_mode->crtc_vsync_end = adjusted_mode->crtc_vsync_start + vsync_width; 318254885Sdumbbell 319254885Sdumbbell} 320254885Sdumbbell 321254885Sdumbbellbool radeon_dig_monitor_is_duallink(struct drm_encoder *encoder, 322254885Sdumbbell u32 pixel_clock) 323254885Sdumbbell{ 324254885Sdumbbell struct drm_device *dev = encoder->dev; 325254885Sdumbbell struct radeon_device *rdev = dev->dev_private; 326254885Sdumbbell struct drm_connector *connector; 327254885Sdumbbell struct radeon_connector *radeon_connector; 328254885Sdumbbell struct radeon_connector_atom_dig *dig_connector; 329254885Sdumbbell 330254885Sdumbbell connector = radeon_get_connector_for_encoder(encoder); 331254885Sdumbbell /* if we don't have an active device yet, just use one of 332254885Sdumbbell * the connectors tied to the encoder. 333254885Sdumbbell */ 334254885Sdumbbell if (!connector) 335254885Sdumbbell connector = radeon_get_connector_for_encoder_init(encoder); 336254885Sdumbbell radeon_connector = to_radeon_connector(connector); 337254885Sdumbbell 338254885Sdumbbell switch (connector->connector_type) { 339254885Sdumbbell case DRM_MODE_CONNECTOR_DVII: 340254885Sdumbbell case DRM_MODE_CONNECTOR_HDMIB: 341254885Sdumbbell if (radeon_connector->use_digital) { 342254885Sdumbbell /* HDMI 1.3 supports up to 340 Mhz over single link */ 343254885Sdumbbell if (ASIC_IS_DCE6(rdev) && drm_detect_hdmi_monitor(radeon_connector->edid)) { 344254885Sdumbbell if (pixel_clock > 340000) 345254885Sdumbbell return true; 346254885Sdumbbell else 347254885Sdumbbell return false; 348254885Sdumbbell } else { 349254885Sdumbbell if (pixel_clock > 165000) 350254885Sdumbbell return true; 351254885Sdumbbell else 352254885Sdumbbell return false; 353254885Sdumbbell } 354254885Sdumbbell } else 355254885Sdumbbell return false; 356254885Sdumbbell case DRM_MODE_CONNECTOR_DVID: 357254885Sdumbbell case DRM_MODE_CONNECTOR_HDMIA: 358254885Sdumbbell case DRM_MODE_CONNECTOR_DisplayPort: 359254885Sdumbbell dig_connector = radeon_connector->con_priv; 360254885Sdumbbell if ((dig_connector->dp_sink_type == CONNECTOR_OBJECT_ID_DISPLAYPORT) || 361254885Sdumbbell (dig_connector->dp_sink_type == CONNECTOR_OBJECT_ID_eDP)) 362254885Sdumbbell return false; 363254885Sdumbbell else { 364254885Sdumbbell /* HDMI 1.3 supports up to 340 Mhz over single link */ 365254885Sdumbbell if (ASIC_IS_DCE6(rdev) && drm_detect_hdmi_monitor(radeon_connector->edid)) { 366254885Sdumbbell if (pixel_clock > 340000) 367254885Sdumbbell return true; 368254885Sdumbbell else 369254885Sdumbbell return false; 370254885Sdumbbell } else { 371254885Sdumbbell if (pixel_clock > 165000) 372254885Sdumbbell return true; 373254885Sdumbbell else 374254885Sdumbbell return false; 375254885Sdumbbell } 376254885Sdumbbell } 377254885Sdumbbell default: 378254885Sdumbbell return false; 379254885Sdumbbell } 380254885Sdumbbell} 381254885Sdumbbell 382