1771fe6b9SJerome Glisse /* 2771fe6b9SJerome Glisse * Copyright 2007-8 Advanced Micro Devices, Inc. 3771fe6b9SJerome Glisse * Copyright 2008 Red Hat Inc. 4771fe6b9SJerome Glisse * 5771fe6b9SJerome Glisse * Permission is hereby granted, free of charge, to any person obtaining a 6771fe6b9SJerome Glisse * copy of this software and associated documentation files (the "Software"), 7771fe6b9SJerome Glisse * to deal in the Software without restriction, including without limitation 8771fe6b9SJerome Glisse * the rights to use, copy, modify, merge, publish, distribute, sublicense, 9771fe6b9SJerome Glisse * and/or sell copies of the Software, and to permit persons to whom the 10771fe6b9SJerome Glisse * Software is furnished to do so, subject to the following conditions: 11771fe6b9SJerome Glisse * 12771fe6b9SJerome Glisse * The above copyright notice and this permission notice shall be included in 13771fe6b9SJerome Glisse * all copies or substantial portions of the Software. 14771fe6b9SJerome Glisse * 15771fe6b9SJerome Glisse * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 16771fe6b9SJerome Glisse * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 17771fe6b9SJerome Glisse * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL 18771fe6b9SJerome Glisse * THE COPYRIGHT HOLDER(S) OR AUTHOR(S) BE LIABLE FOR ANY CLAIM, DAMAGES OR 19771fe6b9SJerome Glisse * OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, 20771fe6b9SJerome Glisse * ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR 21771fe6b9SJerome Glisse * OTHER DEALINGS IN THE SOFTWARE. 22771fe6b9SJerome Glisse * 23771fe6b9SJerome Glisse * Authors: Dave Airlie 24771fe6b9SJerome Glisse * Alex Deucher 25771fe6b9SJerome Glisse */ 26771fe6b9SJerome Glisse #include "drmP.h" 27771fe6b9SJerome Glisse #include "drm_crtc_helper.h" 28771fe6b9SJerome Glisse #include "radeon_drm.h" 29771fe6b9SJerome Glisse #include "radeon.h" 30771fe6b9SJerome Glisse #include "atom.h" 31771fe6b9SJerome Glisse 32771fe6b9SJerome Glisse extern int atom_debug; 33771fe6b9SJerome Glisse 345a9bcaccSAlex Deucher /* evil but including atombios.h is much worse */ 355a9bcaccSAlex Deucher bool radeon_atom_get_tv_timings(struct radeon_device *rdev, int index, 365a9bcaccSAlex Deucher struct drm_display_mode *mode); 375a9bcaccSAlex Deucher 381f3b6a45SDave Airlie static uint32_t radeon_encoder_clones(struct drm_encoder *encoder) 391f3b6a45SDave Airlie { 401f3b6a45SDave Airlie struct drm_device *dev = encoder->dev; 411f3b6a45SDave Airlie struct radeon_device *rdev = dev->dev_private; 421f3b6a45SDave Airlie struct radeon_encoder *radeon_encoder = to_radeon_encoder(encoder); 431f3b6a45SDave Airlie struct drm_encoder *clone_encoder; 441f3b6a45SDave Airlie uint32_t index_mask = 0; 451f3b6a45SDave Airlie int count; 461f3b6a45SDave Airlie 471f3b6a45SDave Airlie /* DIG routing gets problematic */ 481f3b6a45SDave Airlie if (rdev->family >= CHIP_R600) 491f3b6a45SDave Airlie return index_mask; 501f3b6a45SDave Airlie /* LVDS/TV are too wacky */ 511f3b6a45SDave Airlie if (radeon_encoder->devices & ATOM_DEVICE_LCD_SUPPORT) 521f3b6a45SDave Airlie return index_mask; 531f3b6a45SDave Airlie /* DVO requires 2x ppll clocks depending on tmds chip */ 541f3b6a45SDave Airlie if (radeon_encoder->devices & ATOM_DEVICE_DFP2_SUPPORT) 551f3b6a45SDave Airlie return index_mask; 561f3b6a45SDave Airlie 571f3b6a45SDave Airlie count = -1; 581f3b6a45SDave Airlie list_for_each_entry(clone_encoder, &dev->mode_config.encoder_list, head) { 591f3b6a45SDave Airlie struct radeon_encoder *radeon_clone = to_radeon_encoder(clone_encoder); 601f3b6a45SDave Airlie count++; 611f3b6a45SDave Airlie 621f3b6a45SDave Airlie if (clone_encoder == encoder) 631f3b6a45SDave Airlie continue; 641f3b6a45SDave Airlie if (radeon_clone->devices & (ATOM_DEVICE_LCD_SUPPORT)) 651f3b6a45SDave Airlie continue; 661f3b6a45SDave Airlie if (radeon_clone->devices & ATOM_DEVICE_DFP2_SUPPORT) 671f3b6a45SDave Airlie continue; 681f3b6a45SDave Airlie else 691f3b6a45SDave Airlie index_mask |= (1 << count); 701f3b6a45SDave Airlie } 711f3b6a45SDave Airlie return index_mask; 721f3b6a45SDave Airlie } 731f3b6a45SDave Airlie 741f3b6a45SDave Airlie void radeon_setup_encoder_clones(struct drm_device *dev) 751f3b6a45SDave Airlie { 761f3b6a45SDave Airlie struct drm_encoder *encoder; 771f3b6a45SDave Airlie 781f3b6a45SDave Airlie list_for_each_entry(encoder, &dev->mode_config.encoder_list, head) { 791f3b6a45SDave Airlie encoder->possible_clones = radeon_encoder_clones(encoder); 801f3b6a45SDave Airlie } 811f3b6a45SDave Airlie } 821f3b6a45SDave Airlie 83771fe6b9SJerome Glisse uint32_t 84771fe6b9SJerome Glisse radeon_get_encoder_id(struct drm_device *dev, uint32_t supported_device, uint8_t dac) 85771fe6b9SJerome Glisse { 86771fe6b9SJerome Glisse struct radeon_device *rdev = dev->dev_private; 87771fe6b9SJerome Glisse uint32_t ret = 0; 88771fe6b9SJerome Glisse 89771fe6b9SJerome Glisse switch (supported_device) { 90771fe6b9SJerome Glisse case ATOM_DEVICE_CRT1_SUPPORT: 91771fe6b9SJerome Glisse case ATOM_DEVICE_TV1_SUPPORT: 92771fe6b9SJerome Glisse case ATOM_DEVICE_TV2_SUPPORT: 93771fe6b9SJerome Glisse case ATOM_DEVICE_CRT2_SUPPORT: 94771fe6b9SJerome Glisse case ATOM_DEVICE_CV_SUPPORT: 95771fe6b9SJerome Glisse switch (dac) { 96771fe6b9SJerome Glisse case 1: /* dac a */ 97771fe6b9SJerome Glisse if ((rdev->family == CHIP_RS300) || 98771fe6b9SJerome Glisse (rdev->family == CHIP_RS400) || 99771fe6b9SJerome Glisse (rdev->family == CHIP_RS480)) 100771fe6b9SJerome Glisse ret = ENCODER_OBJECT_ID_INTERNAL_DAC2; 101771fe6b9SJerome Glisse else if (ASIC_IS_AVIVO(rdev)) 102771fe6b9SJerome Glisse ret = ENCODER_OBJECT_ID_INTERNAL_KLDSCP_DAC1; 103771fe6b9SJerome Glisse else 104771fe6b9SJerome Glisse ret = ENCODER_OBJECT_ID_INTERNAL_DAC1; 105771fe6b9SJerome Glisse break; 106771fe6b9SJerome Glisse case 2: /* dac b */ 107771fe6b9SJerome Glisse if (ASIC_IS_AVIVO(rdev)) 108771fe6b9SJerome Glisse ret = ENCODER_OBJECT_ID_INTERNAL_KLDSCP_DAC2; 109771fe6b9SJerome Glisse else { 110771fe6b9SJerome Glisse /*if (rdev->family == CHIP_R200) 111771fe6b9SJerome Glisse ret = ENCODER_OBJECT_ID_INTERNAL_DVO1; 112771fe6b9SJerome Glisse else*/ 113771fe6b9SJerome Glisse ret = ENCODER_OBJECT_ID_INTERNAL_DAC2; 114771fe6b9SJerome Glisse } 115771fe6b9SJerome Glisse break; 116771fe6b9SJerome Glisse case 3: /* external dac */ 117771fe6b9SJerome Glisse if (ASIC_IS_AVIVO(rdev)) 118771fe6b9SJerome Glisse ret = ENCODER_OBJECT_ID_INTERNAL_KLDSCP_DVO1; 119771fe6b9SJerome Glisse else 120771fe6b9SJerome Glisse ret = ENCODER_OBJECT_ID_INTERNAL_DVO1; 121771fe6b9SJerome Glisse break; 122771fe6b9SJerome Glisse } 123771fe6b9SJerome Glisse break; 124771fe6b9SJerome Glisse case ATOM_DEVICE_LCD1_SUPPORT: 125771fe6b9SJerome Glisse if (ASIC_IS_AVIVO(rdev)) 126771fe6b9SJerome Glisse ret = ENCODER_OBJECT_ID_INTERNAL_LVTM1; 127771fe6b9SJerome Glisse else 128771fe6b9SJerome Glisse ret = ENCODER_OBJECT_ID_INTERNAL_LVDS; 129771fe6b9SJerome Glisse break; 130771fe6b9SJerome Glisse case ATOM_DEVICE_DFP1_SUPPORT: 131771fe6b9SJerome Glisse if ((rdev->family == CHIP_RS300) || 132771fe6b9SJerome Glisse (rdev->family == CHIP_RS400) || 133771fe6b9SJerome Glisse (rdev->family == CHIP_RS480)) 134771fe6b9SJerome Glisse ret = ENCODER_OBJECT_ID_INTERNAL_DVO1; 135771fe6b9SJerome Glisse else if (ASIC_IS_AVIVO(rdev)) 136771fe6b9SJerome Glisse ret = ENCODER_OBJECT_ID_INTERNAL_KLDSCP_TMDS1; 137771fe6b9SJerome Glisse else 138771fe6b9SJerome Glisse ret = ENCODER_OBJECT_ID_INTERNAL_TMDS1; 139771fe6b9SJerome Glisse break; 140771fe6b9SJerome Glisse case ATOM_DEVICE_LCD2_SUPPORT: 141771fe6b9SJerome Glisse case ATOM_DEVICE_DFP2_SUPPORT: 142771fe6b9SJerome Glisse if ((rdev->family == CHIP_RS600) || 143771fe6b9SJerome Glisse (rdev->family == CHIP_RS690) || 144771fe6b9SJerome Glisse (rdev->family == CHIP_RS740)) 145771fe6b9SJerome Glisse ret = ENCODER_OBJECT_ID_INTERNAL_DDI; 146771fe6b9SJerome Glisse else if (ASIC_IS_AVIVO(rdev)) 147771fe6b9SJerome Glisse ret = ENCODER_OBJECT_ID_INTERNAL_KLDSCP_DVO1; 148771fe6b9SJerome Glisse else 149771fe6b9SJerome Glisse ret = ENCODER_OBJECT_ID_INTERNAL_DVO1; 150771fe6b9SJerome Glisse break; 151771fe6b9SJerome Glisse case ATOM_DEVICE_DFP3_SUPPORT: 152771fe6b9SJerome Glisse ret = ENCODER_OBJECT_ID_INTERNAL_LVTM1; 153771fe6b9SJerome Glisse break; 154771fe6b9SJerome Glisse } 155771fe6b9SJerome Glisse 156771fe6b9SJerome Glisse return ret; 157771fe6b9SJerome Glisse } 158771fe6b9SJerome Glisse 159771fe6b9SJerome Glisse void 160771fe6b9SJerome Glisse radeon_link_encoder_connector(struct drm_device *dev) 161771fe6b9SJerome Glisse { 162771fe6b9SJerome Glisse struct drm_connector *connector; 163771fe6b9SJerome Glisse struct radeon_connector *radeon_connector; 164771fe6b9SJerome Glisse struct drm_encoder *encoder; 165771fe6b9SJerome Glisse struct radeon_encoder *radeon_encoder; 166771fe6b9SJerome Glisse 167771fe6b9SJerome Glisse /* walk the list and link encoders to connectors */ 168771fe6b9SJerome Glisse list_for_each_entry(connector, &dev->mode_config.connector_list, head) { 169771fe6b9SJerome Glisse radeon_connector = to_radeon_connector(connector); 170771fe6b9SJerome Glisse list_for_each_entry(encoder, &dev->mode_config.encoder_list, head) { 171771fe6b9SJerome Glisse radeon_encoder = to_radeon_encoder(encoder); 172771fe6b9SJerome Glisse if (radeon_encoder->devices & radeon_connector->devices) 173771fe6b9SJerome Glisse drm_mode_connector_attach_encoder(connector, encoder); 174771fe6b9SJerome Glisse } 175771fe6b9SJerome Glisse } 176771fe6b9SJerome Glisse } 177771fe6b9SJerome Glisse 1784ce001abSDave Airlie void radeon_encoder_set_active_device(struct drm_encoder *encoder) 1794ce001abSDave Airlie { 1804ce001abSDave Airlie struct drm_device *dev = encoder->dev; 1814ce001abSDave Airlie struct radeon_encoder *radeon_encoder = to_radeon_encoder(encoder); 1824ce001abSDave Airlie struct drm_connector *connector; 1834ce001abSDave Airlie 1844ce001abSDave Airlie list_for_each_entry(connector, &dev->mode_config.connector_list, head) { 1854ce001abSDave Airlie if (connector->encoder == encoder) { 1864ce001abSDave Airlie struct radeon_connector *radeon_connector = to_radeon_connector(connector); 1874ce001abSDave Airlie radeon_encoder->active_device = radeon_encoder->devices & radeon_connector->devices; 188f641e51eSDave Airlie DRM_DEBUG("setting active device to %08x from %08x %08x for encoder %d\n", 1894ce001abSDave Airlie radeon_encoder->active_device, radeon_encoder->devices, 1904ce001abSDave Airlie radeon_connector->devices, encoder->encoder_type); 1914ce001abSDave Airlie } 1924ce001abSDave Airlie } 1934ce001abSDave Airlie } 1944ce001abSDave Airlie 195771fe6b9SJerome Glisse static struct drm_connector * 196771fe6b9SJerome Glisse radeon_get_connector_for_encoder(struct drm_encoder *encoder) 197771fe6b9SJerome Glisse { 198771fe6b9SJerome Glisse struct drm_device *dev = encoder->dev; 199771fe6b9SJerome Glisse struct radeon_encoder *radeon_encoder = to_radeon_encoder(encoder); 200771fe6b9SJerome Glisse struct drm_connector *connector; 201771fe6b9SJerome Glisse struct radeon_connector *radeon_connector; 202771fe6b9SJerome Glisse 203771fe6b9SJerome Glisse list_for_each_entry(connector, &dev->mode_config.connector_list, head) { 204771fe6b9SJerome Glisse radeon_connector = to_radeon_connector(connector); 205*43c33ed8SDave Airlie if (radeon_encoder->active_device & radeon_connector->devices) 206771fe6b9SJerome Glisse return connector; 207771fe6b9SJerome Glisse } 208771fe6b9SJerome Glisse return NULL; 209771fe6b9SJerome Glisse } 210771fe6b9SJerome Glisse 211771fe6b9SJerome Glisse static bool radeon_atom_mode_fixup(struct drm_encoder *encoder, 212771fe6b9SJerome Glisse struct drm_display_mode *mode, 213771fe6b9SJerome Glisse struct drm_display_mode *adjusted_mode) 214771fe6b9SJerome Glisse { 215771fe6b9SJerome Glisse struct radeon_encoder *radeon_encoder = to_radeon_encoder(encoder); 2165a9bcaccSAlex Deucher struct drm_device *dev = encoder->dev; 2175a9bcaccSAlex Deucher struct radeon_device *rdev = dev->dev_private; 218771fe6b9SJerome Glisse 2198c2a6d73SAlex Deucher /* set the active encoder to connector routing */ 2208c2a6d73SAlex Deucher radeon_encoder_set_active_device(encoder); 221771fe6b9SJerome Glisse drm_mode_set_crtcinfo(adjusted_mode, 0); 222771fe6b9SJerome Glisse 223771fe6b9SJerome Glisse /* hw bug */ 224771fe6b9SJerome Glisse if ((mode->flags & DRM_MODE_FLAG_INTERLACE) 225771fe6b9SJerome Glisse && (mode->crtc_vsync_start < (mode->crtc_vdisplay + 2))) 226771fe6b9SJerome Glisse adjusted_mode->crtc_vsync_start = adjusted_mode->crtc_vdisplay + 2; 227771fe6b9SJerome Glisse 22880297e87SAlex Deucher /* get the native mode for LVDS */ 22980297e87SAlex Deucher if (radeon_encoder->active_device & (ATOM_DEVICE_LCD_SUPPORT)) { 23080297e87SAlex Deucher struct drm_display_mode *native_mode = &radeon_encoder->native_mode; 23180297e87SAlex Deucher int mode_id = adjusted_mode->base.id; 23280297e87SAlex Deucher *adjusted_mode = *native_mode; 23380297e87SAlex Deucher if (!ASIC_IS_AVIVO(rdev)) { 23480297e87SAlex Deucher adjusted_mode->hdisplay = mode->hdisplay; 23580297e87SAlex Deucher adjusted_mode->vdisplay = mode->vdisplay; 236310a82c8SAlex Deucher adjusted_mode->crtc_hdisplay = mode->hdisplay; 237310a82c8SAlex Deucher adjusted_mode->crtc_vdisplay = mode->vdisplay; 23880297e87SAlex Deucher } 23980297e87SAlex Deucher adjusted_mode->base.id = mode_id; 24080297e87SAlex Deucher } 24180297e87SAlex Deucher 24280297e87SAlex Deucher /* get the native mode for TV */ 243ceefedd8SAlex Deucher if (radeon_encoder->active_device & (ATOM_DEVICE_TV_SUPPORT)) { 2445a9bcaccSAlex Deucher struct radeon_encoder_atom_dac *tv_dac = radeon_encoder->enc_priv; 2455a9bcaccSAlex Deucher if (tv_dac) { 2465a9bcaccSAlex Deucher if (tv_dac->tv_std == TV_STD_NTSC || 2475a9bcaccSAlex Deucher tv_dac->tv_std == TV_STD_NTSC_J || 2485a9bcaccSAlex Deucher tv_dac->tv_std == TV_STD_PAL_M) 2495a9bcaccSAlex Deucher radeon_atom_get_tv_timings(rdev, 0, adjusted_mode); 2505a9bcaccSAlex Deucher else 2515a9bcaccSAlex Deucher radeon_atom_get_tv_timings(rdev, 1, adjusted_mode); 2525a9bcaccSAlex Deucher } 2535a9bcaccSAlex Deucher } 2545a9bcaccSAlex Deucher 2555801ead6SAlex Deucher if (ASIC_IS_DCE3(rdev) && 2565801ead6SAlex Deucher (radeon_encoder->active_device & (ATOM_DEVICE_DFP_SUPPORT))) { 2575801ead6SAlex Deucher struct drm_connector *connector = radeon_get_connector_for_encoder(encoder); 2585801ead6SAlex Deucher radeon_dp_set_link_config(connector, mode); 2595801ead6SAlex Deucher } 2605801ead6SAlex Deucher 261771fe6b9SJerome Glisse return true; 262771fe6b9SJerome Glisse } 263771fe6b9SJerome Glisse 264771fe6b9SJerome Glisse static void 265771fe6b9SJerome Glisse atombios_dac_setup(struct drm_encoder *encoder, int action) 266771fe6b9SJerome Glisse { 267771fe6b9SJerome Glisse struct drm_device *dev = encoder->dev; 268771fe6b9SJerome Glisse struct radeon_device *rdev = dev->dev_private; 269771fe6b9SJerome Glisse struct radeon_encoder *radeon_encoder = to_radeon_encoder(encoder); 270771fe6b9SJerome Glisse DAC_ENCODER_CONTROL_PS_ALLOCATION args; 271771fe6b9SJerome Glisse int index = 0, num = 0; 272445282dbSDave Airlie struct radeon_encoder_atom_dac *dac_info = radeon_encoder->enc_priv; 273771fe6b9SJerome Glisse enum radeon_tv_std tv_std = TV_STD_NTSC; 274771fe6b9SJerome Glisse 275445282dbSDave Airlie if (dac_info->tv_std) 276445282dbSDave Airlie tv_std = dac_info->tv_std; 277445282dbSDave Airlie 278771fe6b9SJerome Glisse memset(&args, 0, sizeof(args)); 279771fe6b9SJerome Glisse 280771fe6b9SJerome Glisse switch (radeon_encoder->encoder_id) { 281771fe6b9SJerome Glisse case ENCODER_OBJECT_ID_INTERNAL_DAC1: 282771fe6b9SJerome Glisse case ENCODER_OBJECT_ID_INTERNAL_KLDSCP_DAC1: 283771fe6b9SJerome Glisse index = GetIndexIntoMasterTable(COMMAND, DAC1EncoderControl); 284771fe6b9SJerome Glisse num = 1; 285771fe6b9SJerome Glisse break; 286771fe6b9SJerome Glisse case ENCODER_OBJECT_ID_INTERNAL_DAC2: 287771fe6b9SJerome Glisse case ENCODER_OBJECT_ID_INTERNAL_KLDSCP_DAC2: 288771fe6b9SJerome Glisse index = GetIndexIntoMasterTable(COMMAND, DAC2EncoderControl); 289771fe6b9SJerome Glisse num = 2; 290771fe6b9SJerome Glisse break; 291771fe6b9SJerome Glisse } 292771fe6b9SJerome Glisse 293771fe6b9SJerome Glisse args.ucAction = action; 294771fe6b9SJerome Glisse 2954ce001abSDave Airlie if (radeon_encoder->active_device & (ATOM_DEVICE_CRT_SUPPORT)) 296771fe6b9SJerome Glisse args.ucDacStandard = ATOM_DAC1_PS2; 2974ce001abSDave Airlie else if (radeon_encoder->active_device & (ATOM_DEVICE_CV_SUPPORT)) 298771fe6b9SJerome Glisse args.ucDacStandard = ATOM_DAC1_CV; 299771fe6b9SJerome Glisse else { 300771fe6b9SJerome Glisse switch (tv_std) { 301771fe6b9SJerome Glisse case TV_STD_PAL: 302771fe6b9SJerome Glisse case TV_STD_PAL_M: 303771fe6b9SJerome Glisse case TV_STD_SCART_PAL: 304771fe6b9SJerome Glisse case TV_STD_SECAM: 305771fe6b9SJerome Glisse case TV_STD_PAL_CN: 306771fe6b9SJerome Glisse args.ucDacStandard = ATOM_DAC1_PAL; 307771fe6b9SJerome Glisse break; 308771fe6b9SJerome Glisse case TV_STD_NTSC: 309771fe6b9SJerome Glisse case TV_STD_NTSC_J: 310771fe6b9SJerome Glisse case TV_STD_PAL_60: 311771fe6b9SJerome Glisse default: 312771fe6b9SJerome Glisse args.ucDacStandard = ATOM_DAC1_NTSC; 313771fe6b9SJerome Glisse break; 314771fe6b9SJerome Glisse } 315771fe6b9SJerome Glisse } 316771fe6b9SJerome Glisse args.usPixelClock = cpu_to_le16(radeon_encoder->pixel_clock / 10); 317771fe6b9SJerome Glisse 318771fe6b9SJerome Glisse atom_execute_table(rdev->mode_info.atom_context, index, (uint32_t *)&args); 319771fe6b9SJerome Glisse 320771fe6b9SJerome Glisse } 321771fe6b9SJerome Glisse 322771fe6b9SJerome Glisse static void 323771fe6b9SJerome Glisse atombios_tv_setup(struct drm_encoder *encoder, int action) 324771fe6b9SJerome Glisse { 325771fe6b9SJerome Glisse struct drm_device *dev = encoder->dev; 326771fe6b9SJerome Glisse struct radeon_device *rdev = dev->dev_private; 327771fe6b9SJerome Glisse struct radeon_encoder *radeon_encoder = to_radeon_encoder(encoder); 328771fe6b9SJerome Glisse TV_ENCODER_CONTROL_PS_ALLOCATION args; 329771fe6b9SJerome Glisse int index = 0; 330445282dbSDave Airlie struct radeon_encoder_atom_dac *dac_info = radeon_encoder->enc_priv; 331771fe6b9SJerome Glisse enum radeon_tv_std tv_std = TV_STD_NTSC; 332771fe6b9SJerome Glisse 333445282dbSDave Airlie if (dac_info->tv_std) 334445282dbSDave Airlie tv_std = dac_info->tv_std; 335445282dbSDave Airlie 336771fe6b9SJerome Glisse memset(&args, 0, sizeof(args)); 337771fe6b9SJerome Glisse 338771fe6b9SJerome Glisse index = GetIndexIntoMasterTable(COMMAND, TVEncoderControl); 339771fe6b9SJerome Glisse 340771fe6b9SJerome Glisse args.sTVEncoder.ucAction = action; 341771fe6b9SJerome Glisse 3424ce001abSDave Airlie if (radeon_encoder->active_device & (ATOM_DEVICE_CV_SUPPORT)) 343771fe6b9SJerome Glisse args.sTVEncoder.ucTvStandard = ATOM_TV_CV; 344771fe6b9SJerome Glisse else { 345771fe6b9SJerome Glisse switch (tv_std) { 346771fe6b9SJerome Glisse case TV_STD_NTSC: 347771fe6b9SJerome Glisse args.sTVEncoder.ucTvStandard = ATOM_TV_NTSC; 348771fe6b9SJerome Glisse break; 349771fe6b9SJerome Glisse case TV_STD_PAL: 350771fe6b9SJerome Glisse args.sTVEncoder.ucTvStandard = ATOM_TV_PAL; 351771fe6b9SJerome Glisse break; 352771fe6b9SJerome Glisse case TV_STD_PAL_M: 353771fe6b9SJerome Glisse args.sTVEncoder.ucTvStandard = ATOM_TV_PALM; 354771fe6b9SJerome Glisse break; 355771fe6b9SJerome Glisse case TV_STD_PAL_60: 356771fe6b9SJerome Glisse args.sTVEncoder.ucTvStandard = ATOM_TV_PAL60; 357771fe6b9SJerome Glisse break; 358771fe6b9SJerome Glisse case TV_STD_NTSC_J: 359771fe6b9SJerome Glisse args.sTVEncoder.ucTvStandard = ATOM_TV_NTSCJ; 360771fe6b9SJerome Glisse break; 361771fe6b9SJerome Glisse case TV_STD_SCART_PAL: 362771fe6b9SJerome Glisse args.sTVEncoder.ucTvStandard = ATOM_TV_PAL; /* ??? */ 363771fe6b9SJerome Glisse break; 364771fe6b9SJerome Glisse case TV_STD_SECAM: 365771fe6b9SJerome Glisse args.sTVEncoder.ucTvStandard = ATOM_TV_SECAM; 366771fe6b9SJerome Glisse break; 367771fe6b9SJerome Glisse case TV_STD_PAL_CN: 368771fe6b9SJerome Glisse args.sTVEncoder.ucTvStandard = ATOM_TV_PALCN; 369771fe6b9SJerome Glisse break; 370771fe6b9SJerome Glisse default: 371771fe6b9SJerome Glisse args.sTVEncoder.ucTvStandard = ATOM_TV_NTSC; 372771fe6b9SJerome Glisse break; 373771fe6b9SJerome Glisse } 374771fe6b9SJerome Glisse } 375771fe6b9SJerome Glisse 376771fe6b9SJerome Glisse args.sTVEncoder.usPixelClock = cpu_to_le16(radeon_encoder->pixel_clock / 10); 377771fe6b9SJerome Glisse 378771fe6b9SJerome Glisse atom_execute_table(rdev->mode_info.atom_context, index, (uint32_t *)&args); 379771fe6b9SJerome Glisse 380771fe6b9SJerome Glisse } 381771fe6b9SJerome Glisse 382771fe6b9SJerome Glisse void 383771fe6b9SJerome Glisse atombios_external_tmds_setup(struct drm_encoder *encoder, int action) 384771fe6b9SJerome Glisse { 385771fe6b9SJerome Glisse struct drm_device *dev = encoder->dev; 386771fe6b9SJerome Glisse struct radeon_device *rdev = dev->dev_private; 387771fe6b9SJerome Glisse struct radeon_encoder *radeon_encoder = to_radeon_encoder(encoder); 388771fe6b9SJerome Glisse ENABLE_EXTERNAL_TMDS_ENCODER_PS_ALLOCATION args; 389771fe6b9SJerome Glisse int index = 0; 390771fe6b9SJerome Glisse 391771fe6b9SJerome Glisse memset(&args, 0, sizeof(args)); 392771fe6b9SJerome Glisse 393771fe6b9SJerome Glisse index = GetIndexIntoMasterTable(COMMAND, DVOEncoderControl); 394771fe6b9SJerome Glisse 395771fe6b9SJerome Glisse args.sXTmdsEncoder.ucEnable = action; 396771fe6b9SJerome Glisse 397771fe6b9SJerome Glisse if (radeon_encoder->pixel_clock > 165000) 398771fe6b9SJerome Glisse args.sXTmdsEncoder.ucMisc = PANEL_ENCODER_MISC_DUAL; 399771fe6b9SJerome Glisse 400771fe6b9SJerome Glisse /*if (pScrn->rgbBits == 8)*/ 401771fe6b9SJerome Glisse args.sXTmdsEncoder.ucMisc |= (1 << 1); 402771fe6b9SJerome Glisse 403771fe6b9SJerome Glisse atom_execute_table(rdev->mode_info.atom_context, index, (uint32_t *)&args); 404771fe6b9SJerome Glisse 405771fe6b9SJerome Glisse } 406771fe6b9SJerome Glisse 407771fe6b9SJerome Glisse static void 408771fe6b9SJerome Glisse atombios_ddia_setup(struct drm_encoder *encoder, int action) 409771fe6b9SJerome Glisse { 410771fe6b9SJerome Glisse struct drm_device *dev = encoder->dev; 411771fe6b9SJerome Glisse struct radeon_device *rdev = dev->dev_private; 412771fe6b9SJerome Glisse struct radeon_encoder *radeon_encoder = to_radeon_encoder(encoder); 413771fe6b9SJerome Glisse DVO_ENCODER_CONTROL_PS_ALLOCATION args; 414771fe6b9SJerome Glisse int index = 0; 415771fe6b9SJerome Glisse 416771fe6b9SJerome Glisse memset(&args, 0, sizeof(args)); 417771fe6b9SJerome Glisse 418771fe6b9SJerome Glisse index = GetIndexIntoMasterTable(COMMAND, DVOEncoderControl); 419771fe6b9SJerome Glisse 420771fe6b9SJerome Glisse args.sDVOEncoder.ucAction = action; 421771fe6b9SJerome Glisse args.sDVOEncoder.usPixelClock = cpu_to_le16(radeon_encoder->pixel_clock / 10); 422771fe6b9SJerome Glisse 423771fe6b9SJerome Glisse if (radeon_encoder->pixel_clock > 165000) 424771fe6b9SJerome Glisse args.sDVOEncoder.usDevAttr.sDigAttrib.ucAttribute = PANEL_ENCODER_MISC_DUAL; 425771fe6b9SJerome Glisse 426771fe6b9SJerome Glisse atom_execute_table(rdev->mode_info.atom_context, index, (uint32_t *)&args); 427771fe6b9SJerome Glisse 428771fe6b9SJerome Glisse } 429771fe6b9SJerome Glisse 430771fe6b9SJerome Glisse union lvds_encoder_control { 431771fe6b9SJerome Glisse LVDS_ENCODER_CONTROL_PS_ALLOCATION v1; 432771fe6b9SJerome Glisse LVDS_ENCODER_CONTROL_PS_ALLOCATION_V2 v2; 433771fe6b9SJerome Glisse }; 434771fe6b9SJerome Glisse 43532f48ffeSAlex Deucher void 436771fe6b9SJerome Glisse atombios_digital_setup(struct drm_encoder *encoder, int action) 437771fe6b9SJerome Glisse { 438771fe6b9SJerome Glisse struct drm_device *dev = encoder->dev; 439771fe6b9SJerome Glisse struct radeon_device *rdev = dev->dev_private; 440771fe6b9SJerome Glisse struct radeon_encoder *radeon_encoder = to_radeon_encoder(encoder); 441771fe6b9SJerome Glisse union lvds_encoder_control args; 442771fe6b9SJerome Glisse int index = 0; 443dafc3bd5SChristian Koenig int hdmi_detected = 0; 444771fe6b9SJerome Glisse uint8_t frev, crev; 445771fe6b9SJerome Glisse struct radeon_encoder_atom_dig *dig; 446771fe6b9SJerome Glisse struct drm_connector *connector; 447771fe6b9SJerome Glisse struct radeon_connector *radeon_connector; 448771fe6b9SJerome Glisse struct radeon_connector_atom_dig *dig_connector; 449771fe6b9SJerome Glisse 450771fe6b9SJerome Glisse connector = radeon_get_connector_for_encoder(encoder); 451771fe6b9SJerome Glisse if (!connector) 452771fe6b9SJerome Glisse return; 453771fe6b9SJerome Glisse 454771fe6b9SJerome Glisse radeon_connector = to_radeon_connector(connector); 455771fe6b9SJerome Glisse 456771fe6b9SJerome Glisse if (!radeon_encoder->enc_priv) 457771fe6b9SJerome Glisse return; 458771fe6b9SJerome Glisse 459771fe6b9SJerome Glisse dig = radeon_encoder->enc_priv; 460771fe6b9SJerome Glisse 461771fe6b9SJerome Glisse if (!radeon_connector->con_priv) 462771fe6b9SJerome Glisse return; 463771fe6b9SJerome Glisse 464dafc3bd5SChristian Koenig if (drm_detect_hdmi_monitor(radeon_connector->edid)) 465dafc3bd5SChristian Koenig hdmi_detected = 1; 466dafc3bd5SChristian Koenig 467771fe6b9SJerome Glisse dig_connector = radeon_connector->con_priv; 468771fe6b9SJerome Glisse 469771fe6b9SJerome Glisse memset(&args, 0, sizeof(args)); 470771fe6b9SJerome Glisse 471771fe6b9SJerome Glisse switch (radeon_encoder->encoder_id) { 472771fe6b9SJerome Glisse case ENCODER_OBJECT_ID_INTERNAL_LVDS: 473771fe6b9SJerome Glisse index = GetIndexIntoMasterTable(COMMAND, LVDSEncoderControl); 474771fe6b9SJerome Glisse break; 475771fe6b9SJerome Glisse case ENCODER_OBJECT_ID_INTERNAL_TMDS1: 476771fe6b9SJerome Glisse case ENCODER_OBJECT_ID_INTERNAL_KLDSCP_TMDS1: 477771fe6b9SJerome Glisse index = GetIndexIntoMasterTable(COMMAND, TMDS1EncoderControl); 478771fe6b9SJerome Glisse break; 479771fe6b9SJerome Glisse case ENCODER_OBJECT_ID_INTERNAL_LVTM1: 480771fe6b9SJerome Glisse if (radeon_encoder->devices & (ATOM_DEVICE_LCD_SUPPORT)) 481771fe6b9SJerome Glisse index = GetIndexIntoMasterTable(COMMAND, LVDSEncoderControl); 482771fe6b9SJerome Glisse else 483771fe6b9SJerome Glisse index = GetIndexIntoMasterTable(COMMAND, TMDS2EncoderControl); 484771fe6b9SJerome Glisse break; 485771fe6b9SJerome Glisse } 486771fe6b9SJerome Glisse 487771fe6b9SJerome Glisse atom_parse_cmd_header(rdev->mode_info.atom_context, index, &frev, &crev); 488771fe6b9SJerome Glisse 489771fe6b9SJerome Glisse switch (frev) { 490771fe6b9SJerome Glisse case 1: 491771fe6b9SJerome Glisse case 2: 492771fe6b9SJerome Glisse switch (crev) { 493771fe6b9SJerome Glisse case 1: 494771fe6b9SJerome Glisse args.v1.ucMisc = 0; 495771fe6b9SJerome Glisse args.v1.ucAction = action; 496dafc3bd5SChristian Koenig if (hdmi_detected) 497771fe6b9SJerome Glisse args.v1.ucMisc |= PANEL_ENCODER_MISC_HDMI_TYPE; 498771fe6b9SJerome Glisse args.v1.usPixelClock = cpu_to_le16(radeon_encoder->pixel_clock / 10); 499771fe6b9SJerome Glisse if (radeon_encoder->devices & (ATOM_DEVICE_LCD_SUPPORT)) { 500edc664e3SAlex Deucher if (dig->lvds_misc & ATOM_PANEL_MISC_DUAL) 501771fe6b9SJerome Glisse args.v1.ucMisc |= PANEL_ENCODER_MISC_DUAL; 502edc664e3SAlex Deucher if (dig->lvds_misc & ATOM_PANEL_MISC_888RGB) 503771fe6b9SJerome Glisse args.v1.ucMisc |= (1 << 1); 504771fe6b9SJerome Glisse } else { 505771fe6b9SJerome Glisse if (dig_connector->linkb) 506771fe6b9SJerome Glisse args.v1.ucMisc |= PANEL_ENCODER_MISC_TMDS_LINKB; 507771fe6b9SJerome Glisse if (radeon_encoder->pixel_clock > 165000) 508771fe6b9SJerome Glisse args.v1.ucMisc |= PANEL_ENCODER_MISC_DUAL; 509771fe6b9SJerome Glisse /*if (pScrn->rgbBits == 8) */ 510771fe6b9SJerome Glisse args.v1.ucMisc |= (1 << 1); 511771fe6b9SJerome Glisse } 512771fe6b9SJerome Glisse break; 513771fe6b9SJerome Glisse case 2: 514771fe6b9SJerome Glisse case 3: 515771fe6b9SJerome Glisse args.v2.ucMisc = 0; 516771fe6b9SJerome Glisse args.v2.ucAction = action; 517771fe6b9SJerome Glisse if (crev == 3) { 518771fe6b9SJerome Glisse if (dig->coherent_mode) 519771fe6b9SJerome Glisse args.v2.ucMisc |= PANEL_ENCODER_MISC_COHERENT; 520771fe6b9SJerome Glisse } 521dafc3bd5SChristian Koenig if (hdmi_detected) 522771fe6b9SJerome Glisse args.v2.ucMisc |= PANEL_ENCODER_MISC_HDMI_TYPE; 523771fe6b9SJerome Glisse args.v2.usPixelClock = cpu_to_le16(radeon_encoder->pixel_clock / 10); 524771fe6b9SJerome Glisse args.v2.ucTruncate = 0; 525771fe6b9SJerome Glisse args.v2.ucSpatial = 0; 526771fe6b9SJerome Glisse args.v2.ucTemporal = 0; 527771fe6b9SJerome Glisse args.v2.ucFRC = 0; 528771fe6b9SJerome Glisse if (radeon_encoder->devices & (ATOM_DEVICE_LCD_SUPPORT)) { 529edc664e3SAlex Deucher if (dig->lvds_misc & ATOM_PANEL_MISC_DUAL) 530771fe6b9SJerome Glisse args.v2.ucMisc |= PANEL_ENCODER_MISC_DUAL; 531edc664e3SAlex Deucher if (dig->lvds_misc & ATOM_PANEL_MISC_SPATIAL) { 532771fe6b9SJerome Glisse args.v2.ucSpatial = PANEL_ENCODER_SPATIAL_DITHER_EN; 533edc664e3SAlex Deucher if (dig->lvds_misc & ATOM_PANEL_MISC_888RGB) 534771fe6b9SJerome Glisse args.v2.ucSpatial |= PANEL_ENCODER_SPATIAL_DITHER_DEPTH; 535771fe6b9SJerome Glisse } 536edc664e3SAlex Deucher if (dig->lvds_misc & ATOM_PANEL_MISC_TEMPORAL) { 537771fe6b9SJerome Glisse args.v2.ucTemporal = PANEL_ENCODER_TEMPORAL_DITHER_EN; 538edc664e3SAlex Deucher if (dig->lvds_misc & ATOM_PANEL_MISC_888RGB) 539771fe6b9SJerome Glisse args.v2.ucTemporal |= PANEL_ENCODER_TEMPORAL_DITHER_DEPTH; 540edc664e3SAlex Deucher if (((dig->lvds_misc >> ATOM_PANEL_MISC_GREY_LEVEL_SHIFT) & 0x3) == 2) 541771fe6b9SJerome Glisse args.v2.ucTemporal |= PANEL_ENCODER_TEMPORAL_LEVEL_4; 542771fe6b9SJerome Glisse } 543771fe6b9SJerome Glisse } else { 544771fe6b9SJerome Glisse if (dig_connector->linkb) 545771fe6b9SJerome Glisse args.v2.ucMisc |= PANEL_ENCODER_MISC_TMDS_LINKB; 546771fe6b9SJerome Glisse if (radeon_encoder->pixel_clock > 165000) 547771fe6b9SJerome Glisse args.v2.ucMisc |= PANEL_ENCODER_MISC_DUAL; 548771fe6b9SJerome Glisse } 549771fe6b9SJerome Glisse break; 550771fe6b9SJerome Glisse default: 551771fe6b9SJerome Glisse DRM_ERROR("Unknown table version %d, %d\n", frev, crev); 552771fe6b9SJerome Glisse break; 553771fe6b9SJerome Glisse } 554771fe6b9SJerome Glisse break; 555771fe6b9SJerome Glisse default: 556771fe6b9SJerome Glisse DRM_ERROR("Unknown table version %d, %d\n", frev, crev); 557771fe6b9SJerome Glisse break; 558771fe6b9SJerome Glisse } 559771fe6b9SJerome Glisse 560771fe6b9SJerome Glisse atom_execute_table(rdev->mode_info.atom_context, index, (uint32_t *)&args); 561dafc3bd5SChristian Koenig r600_hdmi_enable(encoder, hdmi_detected); 562771fe6b9SJerome Glisse } 563771fe6b9SJerome Glisse 564771fe6b9SJerome Glisse int 565771fe6b9SJerome Glisse atombios_get_encoder_mode(struct drm_encoder *encoder) 566771fe6b9SJerome Glisse { 567771fe6b9SJerome Glisse struct drm_connector *connector; 568771fe6b9SJerome Glisse struct radeon_connector *radeon_connector; 569f92a8b67SAlex Deucher struct radeon_connector_atom_dig *radeon_dig_connector; 570771fe6b9SJerome Glisse 571771fe6b9SJerome Glisse connector = radeon_get_connector_for_encoder(encoder); 572771fe6b9SJerome Glisse if (!connector) 573771fe6b9SJerome Glisse return 0; 574771fe6b9SJerome Glisse 575771fe6b9SJerome Glisse radeon_connector = to_radeon_connector(connector); 576771fe6b9SJerome Glisse 577771fe6b9SJerome Glisse switch (connector->connector_type) { 578771fe6b9SJerome Glisse case DRM_MODE_CONNECTOR_DVII: 579705af9c7SAlex Deucher case DRM_MODE_CONNECTOR_HDMIB: /* HDMI-B is basically DL-DVI; analog works fine */ 5800294cf4fSAlex Deucher if (drm_detect_hdmi_monitor(radeon_connector->edid)) 581771fe6b9SJerome Glisse return ATOM_ENCODER_MODE_HDMI; 582771fe6b9SJerome Glisse else if (radeon_connector->use_digital) 583771fe6b9SJerome Glisse return ATOM_ENCODER_MODE_DVI; 584771fe6b9SJerome Glisse else 585771fe6b9SJerome Glisse return ATOM_ENCODER_MODE_CRT; 586771fe6b9SJerome Glisse break; 587771fe6b9SJerome Glisse case DRM_MODE_CONNECTOR_DVID: 588771fe6b9SJerome Glisse case DRM_MODE_CONNECTOR_HDMIA: 589771fe6b9SJerome Glisse default: 5900294cf4fSAlex Deucher if (drm_detect_hdmi_monitor(radeon_connector->edid)) 591771fe6b9SJerome Glisse return ATOM_ENCODER_MODE_HDMI; 592771fe6b9SJerome Glisse else 593771fe6b9SJerome Glisse return ATOM_ENCODER_MODE_DVI; 594771fe6b9SJerome Glisse break; 595771fe6b9SJerome Glisse case DRM_MODE_CONNECTOR_LVDS: 596771fe6b9SJerome Glisse return ATOM_ENCODER_MODE_LVDS; 597771fe6b9SJerome Glisse break; 598771fe6b9SJerome Glisse case DRM_MODE_CONNECTOR_DisplayPort: 599196c58d2SAlex Deucher case DRM_MODE_CONNECTOR_eDP: 600f92a8b67SAlex Deucher radeon_dig_connector = radeon_connector->con_priv; 601196c58d2SAlex Deucher if ((radeon_dig_connector->dp_sink_type == CONNECTOR_OBJECT_ID_DISPLAYPORT) || 602196c58d2SAlex Deucher (radeon_dig_connector->dp_sink_type == CONNECTOR_OBJECT_ID_eDP)) 603771fe6b9SJerome Glisse return ATOM_ENCODER_MODE_DP; 604f92a8b67SAlex Deucher else if (drm_detect_hdmi_monitor(radeon_connector->edid)) 605771fe6b9SJerome Glisse return ATOM_ENCODER_MODE_HDMI; 606771fe6b9SJerome Glisse else 607771fe6b9SJerome Glisse return ATOM_ENCODER_MODE_DVI; 608771fe6b9SJerome Glisse break; 609a5899fccSAlex Deucher case DRM_MODE_CONNECTOR_DVIA: 610a5899fccSAlex Deucher case DRM_MODE_CONNECTOR_VGA: 611771fe6b9SJerome Glisse return ATOM_ENCODER_MODE_CRT; 612771fe6b9SJerome Glisse break; 613a5899fccSAlex Deucher case DRM_MODE_CONNECTOR_Composite: 614a5899fccSAlex Deucher case DRM_MODE_CONNECTOR_SVIDEO: 615a5899fccSAlex Deucher case DRM_MODE_CONNECTOR_9PinDIN: 616771fe6b9SJerome Glisse /* fix me */ 617771fe6b9SJerome Glisse return ATOM_ENCODER_MODE_TV; 618771fe6b9SJerome Glisse /*return ATOM_ENCODER_MODE_CV;*/ 619771fe6b9SJerome Glisse break; 620771fe6b9SJerome Glisse } 621771fe6b9SJerome Glisse } 622771fe6b9SJerome Glisse 6231a66c95aSAlex Deucher /* 6241a66c95aSAlex Deucher * DIG Encoder/Transmitter Setup 6251a66c95aSAlex Deucher * 6261a66c95aSAlex Deucher * DCE 3.0/3.1 6271a66c95aSAlex Deucher * - 2 DIG transmitter blocks. UNIPHY (links A and B) and LVTMA. 6281a66c95aSAlex Deucher * Supports up to 3 digital outputs 6291a66c95aSAlex Deucher * - 2 DIG encoder blocks. 6301a66c95aSAlex Deucher * DIG1 can drive UNIPHY link A or link B 6311a66c95aSAlex Deucher * DIG2 can drive UNIPHY link B or LVTMA 6321a66c95aSAlex Deucher * 6331a66c95aSAlex Deucher * DCE 3.2 6341a66c95aSAlex Deucher * - 3 DIG transmitter blocks. UNIPHY0/1/2 (links A and B). 6351a66c95aSAlex Deucher * Supports up to 5 digital outputs 6361a66c95aSAlex Deucher * - 2 DIG encoder blocks. 6371a66c95aSAlex Deucher * DIG1/2 can drive UNIPHY0/1/2 link A or link B 6381a66c95aSAlex Deucher * 6391a66c95aSAlex Deucher * Routing 6401a66c95aSAlex Deucher * crtc -> dig encoder -> UNIPHY/LVTMA (1 or 2 links) 6411a66c95aSAlex Deucher * Examples: 6421a66c95aSAlex Deucher * crtc0 -> dig2 -> LVTMA links A+B -> TMDS/HDMI 6431a66c95aSAlex Deucher * crtc1 -> dig1 -> UNIPHY0 link B -> DP 6441a66c95aSAlex Deucher * crtc0 -> dig1 -> UNIPHY2 link A -> LVDS 6451a66c95aSAlex Deucher * crtc1 -> dig2 -> UNIPHY1 link B+A -> TMDS/HDMI 6461a66c95aSAlex Deucher */ 647771fe6b9SJerome Glisse static void 648771fe6b9SJerome Glisse atombios_dig_encoder_setup(struct drm_encoder *encoder, int action) 649771fe6b9SJerome Glisse { 650771fe6b9SJerome Glisse struct drm_device *dev = encoder->dev; 651771fe6b9SJerome Glisse struct radeon_device *rdev = dev->dev_private; 652771fe6b9SJerome Glisse struct radeon_encoder *radeon_encoder = to_radeon_encoder(encoder); 653771fe6b9SJerome Glisse DIG_ENCODER_CONTROL_PS_ALLOCATION args; 654771fe6b9SJerome Glisse int index = 0, num = 0; 655771fe6b9SJerome Glisse uint8_t frev, crev; 656771fe6b9SJerome Glisse struct radeon_encoder_atom_dig *dig; 657771fe6b9SJerome Glisse struct drm_connector *connector; 658771fe6b9SJerome Glisse struct radeon_connector *radeon_connector; 659771fe6b9SJerome Glisse struct radeon_connector_atom_dig *dig_connector; 660771fe6b9SJerome Glisse 661771fe6b9SJerome Glisse connector = radeon_get_connector_for_encoder(encoder); 662771fe6b9SJerome Glisse if (!connector) 663771fe6b9SJerome Glisse return; 664771fe6b9SJerome Glisse 665771fe6b9SJerome Glisse radeon_connector = to_radeon_connector(connector); 666771fe6b9SJerome Glisse 667771fe6b9SJerome Glisse if (!radeon_connector->con_priv) 668771fe6b9SJerome Glisse return; 669771fe6b9SJerome Glisse 670771fe6b9SJerome Glisse dig_connector = radeon_connector->con_priv; 671771fe6b9SJerome Glisse 672771fe6b9SJerome Glisse if (!radeon_encoder->enc_priv) 673771fe6b9SJerome Glisse return; 674771fe6b9SJerome Glisse 675771fe6b9SJerome Glisse dig = radeon_encoder->enc_priv; 676771fe6b9SJerome Glisse 677771fe6b9SJerome Glisse memset(&args, 0, sizeof(args)); 678771fe6b9SJerome Glisse 679771fe6b9SJerome Glisse if (ASIC_IS_DCE32(rdev)) { 680771fe6b9SJerome Glisse if (dig->dig_block) 681771fe6b9SJerome Glisse index = GetIndexIntoMasterTable(COMMAND, DIG2EncoderControl); 682771fe6b9SJerome Glisse else 683771fe6b9SJerome Glisse index = GetIndexIntoMasterTable(COMMAND, DIG1EncoderControl); 684771fe6b9SJerome Glisse num = dig->dig_block + 1; 685771fe6b9SJerome Glisse } else { 686771fe6b9SJerome Glisse switch (radeon_encoder->encoder_id) { 687771fe6b9SJerome Glisse case ENCODER_OBJECT_ID_INTERNAL_UNIPHY: 6881a66c95aSAlex Deucher /* XXX doesn't really matter which dig encoder we pick as long as it's 6891a66c95aSAlex Deucher * not already in use 6901a66c95aSAlex Deucher */ 6911a66c95aSAlex Deucher if (dig_connector->linkb) 6921a66c95aSAlex Deucher index = GetIndexIntoMasterTable(COMMAND, DIG2EncoderControl); 6931a66c95aSAlex Deucher else 694771fe6b9SJerome Glisse index = GetIndexIntoMasterTable(COMMAND, DIG1EncoderControl); 695771fe6b9SJerome Glisse num = 1; 696771fe6b9SJerome Glisse break; 697771fe6b9SJerome Glisse case ENCODER_OBJECT_ID_INTERNAL_KLDSCP_LVTMA: 6981a66c95aSAlex Deucher /* Only dig2 encoder can drive LVTMA */ 699771fe6b9SJerome Glisse index = GetIndexIntoMasterTable(COMMAND, DIG2EncoderControl); 700771fe6b9SJerome Glisse num = 2; 701771fe6b9SJerome Glisse break; 702771fe6b9SJerome Glisse } 703771fe6b9SJerome Glisse } 704771fe6b9SJerome Glisse 705771fe6b9SJerome Glisse atom_parse_cmd_header(rdev->mode_info.atom_context, index, &frev, &crev); 706771fe6b9SJerome Glisse 707771fe6b9SJerome Glisse args.ucAction = action; 708771fe6b9SJerome Glisse args.usPixelClock = cpu_to_le16(radeon_encoder->pixel_clock / 10); 709771fe6b9SJerome Glisse 710771fe6b9SJerome Glisse if (ASIC_IS_DCE32(rdev)) { 711771fe6b9SJerome Glisse switch (radeon_encoder->encoder_id) { 712771fe6b9SJerome Glisse case ENCODER_OBJECT_ID_INTERNAL_UNIPHY: 713771fe6b9SJerome Glisse args.ucConfig = ATOM_ENCODER_CONFIG_V2_TRANSMITTER1; 714771fe6b9SJerome Glisse break; 715771fe6b9SJerome Glisse case ENCODER_OBJECT_ID_INTERNAL_UNIPHY1: 716771fe6b9SJerome Glisse args.ucConfig = ATOM_ENCODER_CONFIG_V2_TRANSMITTER2; 717771fe6b9SJerome Glisse break; 718771fe6b9SJerome Glisse case ENCODER_OBJECT_ID_INTERNAL_UNIPHY2: 719771fe6b9SJerome Glisse args.ucConfig = ATOM_ENCODER_CONFIG_V2_TRANSMITTER3; 720771fe6b9SJerome Glisse break; 721771fe6b9SJerome Glisse } 722771fe6b9SJerome Glisse } else { 723771fe6b9SJerome Glisse switch (radeon_encoder->encoder_id) { 724771fe6b9SJerome Glisse case ENCODER_OBJECT_ID_INTERNAL_UNIPHY: 725771fe6b9SJerome Glisse args.ucConfig = ATOM_ENCODER_CONFIG_TRANSMITTER1; 726771fe6b9SJerome Glisse break; 727771fe6b9SJerome Glisse case ENCODER_OBJECT_ID_INTERNAL_KLDSCP_LVTMA: 728771fe6b9SJerome Glisse args.ucConfig = ATOM_ENCODER_CONFIG_TRANSMITTER2; 729771fe6b9SJerome Glisse break; 730771fe6b9SJerome Glisse } 731771fe6b9SJerome Glisse } 732771fe6b9SJerome Glisse 733f92a8b67SAlex Deucher args.ucEncoderMode = atombios_get_encoder_mode(encoder); 734f92a8b67SAlex Deucher 735f92a8b67SAlex Deucher if (args.ucEncoderMode == ATOM_ENCODER_MODE_DP) { 7365801ead6SAlex Deucher if (dig_connector->dp_clock == 270000) 737f92a8b67SAlex Deucher args.ucConfig |= ATOM_ENCODER_CONFIG_DPLINKRATE_2_70GHZ; 7385801ead6SAlex Deucher args.ucLaneNum = dig_connector->dp_lane_count; 739f92a8b67SAlex Deucher } else if (radeon_encoder->pixel_clock > 165000) 740771fe6b9SJerome Glisse args.ucLaneNum = 8; 7411a66c95aSAlex Deucher else 7421a66c95aSAlex Deucher args.ucLaneNum = 4; 7431a66c95aSAlex Deucher 744771fe6b9SJerome Glisse if (dig_connector->linkb) 745771fe6b9SJerome Glisse args.ucConfig |= ATOM_ENCODER_CONFIG_LINKB; 746771fe6b9SJerome Glisse else 747771fe6b9SJerome Glisse args.ucConfig |= ATOM_ENCODER_CONFIG_LINKA; 748771fe6b9SJerome Glisse 749771fe6b9SJerome Glisse atom_execute_table(rdev->mode_info.atom_context, index, (uint32_t *)&args); 750771fe6b9SJerome Glisse 751771fe6b9SJerome Glisse } 752771fe6b9SJerome Glisse 753771fe6b9SJerome Glisse union dig_transmitter_control { 754771fe6b9SJerome Glisse DIG_TRANSMITTER_CONTROL_PS_ALLOCATION v1; 755771fe6b9SJerome Glisse DIG_TRANSMITTER_CONTROL_PARAMETERS_V2 v2; 756771fe6b9SJerome Glisse }; 757771fe6b9SJerome Glisse 7585801ead6SAlex Deucher void 7591a66c95aSAlex Deucher atombios_dig_transmitter_setup(struct drm_encoder *encoder, int action, uint8_t lane_num, uint8_t lane_set) 760771fe6b9SJerome Glisse { 761771fe6b9SJerome Glisse struct drm_device *dev = encoder->dev; 762771fe6b9SJerome Glisse struct radeon_device *rdev = dev->dev_private; 763771fe6b9SJerome Glisse struct radeon_encoder *radeon_encoder = to_radeon_encoder(encoder); 764771fe6b9SJerome Glisse union dig_transmitter_control args; 765771fe6b9SJerome Glisse int index = 0, num = 0; 766771fe6b9SJerome Glisse uint8_t frev, crev; 767771fe6b9SJerome Glisse struct radeon_encoder_atom_dig *dig; 768771fe6b9SJerome Glisse struct drm_connector *connector; 769771fe6b9SJerome Glisse struct radeon_connector *radeon_connector; 770771fe6b9SJerome Glisse struct radeon_connector_atom_dig *dig_connector; 771f92a8b67SAlex Deucher bool is_dp = false; 772771fe6b9SJerome Glisse 773771fe6b9SJerome Glisse connector = radeon_get_connector_for_encoder(encoder); 774771fe6b9SJerome Glisse if (!connector) 775771fe6b9SJerome Glisse return; 776771fe6b9SJerome Glisse 777771fe6b9SJerome Glisse radeon_connector = to_radeon_connector(connector); 778771fe6b9SJerome Glisse 779771fe6b9SJerome Glisse if (!radeon_encoder->enc_priv) 780771fe6b9SJerome Glisse return; 781771fe6b9SJerome Glisse 782771fe6b9SJerome Glisse dig = radeon_encoder->enc_priv; 783771fe6b9SJerome Glisse 784771fe6b9SJerome Glisse if (!radeon_connector->con_priv) 785771fe6b9SJerome Glisse return; 786771fe6b9SJerome Glisse 787771fe6b9SJerome Glisse dig_connector = radeon_connector->con_priv; 788771fe6b9SJerome Glisse 789f92a8b67SAlex Deucher if (atombios_get_encoder_mode(encoder) == ATOM_ENCODER_MODE_DP) 790f92a8b67SAlex Deucher is_dp = true; 791f92a8b67SAlex Deucher 792771fe6b9SJerome Glisse memset(&args, 0, sizeof(args)); 793771fe6b9SJerome Glisse 794771fe6b9SJerome Glisse if (ASIC_IS_DCE32(rdev)) 795771fe6b9SJerome Glisse index = GetIndexIntoMasterTable(COMMAND, UNIPHYTransmitterControl); 796771fe6b9SJerome Glisse else { 797771fe6b9SJerome Glisse switch (radeon_encoder->encoder_id) { 798771fe6b9SJerome Glisse case ENCODER_OBJECT_ID_INTERNAL_UNIPHY: 799771fe6b9SJerome Glisse index = GetIndexIntoMasterTable(COMMAND, DIG1TransmitterControl); 800771fe6b9SJerome Glisse break; 801771fe6b9SJerome Glisse case ENCODER_OBJECT_ID_INTERNAL_KLDSCP_LVTMA: 802771fe6b9SJerome Glisse index = GetIndexIntoMasterTable(COMMAND, DIG2TransmitterControl); 803771fe6b9SJerome Glisse break; 804771fe6b9SJerome Glisse } 805771fe6b9SJerome Glisse } 806771fe6b9SJerome Glisse 807771fe6b9SJerome Glisse atom_parse_cmd_header(rdev->mode_info.atom_context, index, &frev, &crev); 808771fe6b9SJerome Glisse 809771fe6b9SJerome Glisse args.v1.ucAction = action; 810f95a9f0bSAlex Deucher if (action == ATOM_TRANSMITTER_ACTION_INIT) { 811f95a9f0bSAlex Deucher args.v1.usInitInfo = radeon_connector->connector_object_id; 8121a66c95aSAlex Deucher } else if (action == ATOM_TRANSMITTER_ACTION_SETUP_VSEMPH) { 8131a66c95aSAlex Deucher args.v1.asMode.ucLaneSel = lane_num; 8141a66c95aSAlex Deucher args.v1.asMode.ucLaneSet = lane_set; 815771fe6b9SJerome Glisse } else { 816f92a8b67SAlex Deucher if (is_dp) 817f92a8b67SAlex Deucher args.v1.usPixelClock = 8185801ead6SAlex Deucher cpu_to_le16(dig_connector->dp_clock / 10); 819f92a8b67SAlex Deucher else if (radeon_encoder->pixel_clock > 165000) 820f95a9f0bSAlex Deucher args.v1.usPixelClock = cpu_to_le16((radeon_encoder->pixel_clock / 2) / 10); 821f95a9f0bSAlex Deucher else 822f95a9f0bSAlex Deucher args.v1.usPixelClock = cpu_to_le16(radeon_encoder->pixel_clock / 10); 823771fe6b9SJerome Glisse } 824f95a9f0bSAlex Deucher if (ASIC_IS_DCE32(rdev)) { 825771fe6b9SJerome Glisse if (dig->dig_block) 826771fe6b9SJerome Glisse args.v2.acConfig.ucEncoderSel = 1; 8271a66c95aSAlex Deucher if (dig_connector->linkb) 8281a66c95aSAlex Deucher args.v2.acConfig.ucLinkSel = 1; 829771fe6b9SJerome Glisse 830771fe6b9SJerome Glisse switch (radeon_encoder->encoder_id) { 831771fe6b9SJerome Glisse case ENCODER_OBJECT_ID_INTERNAL_UNIPHY: 832771fe6b9SJerome Glisse args.v2.acConfig.ucTransmitterSel = 0; 833771fe6b9SJerome Glisse num = 0; 834771fe6b9SJerome Glisse break; 835771fe6b9SJerome Glisse case ENCODER_OBJECT_ID_INTERNAL_UNIPHY1: 836771fe6b9SJerome Glisse args.v2.acConfig.ucTransmitterSel = 1; 837771fe6b9SJerome Glisse num = 1; 838771fe6b9SJerome Glisse break; 839771fe6b9SJerome Glisse case ENCODER_OBJECT_ID_INTERNAL_UNIPHY2: 840771fe6b9SJerome Glisse args.v2.acConfig.ucTransmitterSel = 2; 841771fe6b9SJerome Glisse num = 2; 842771fe6b9SJerome Glisse break; 843771fe6b9SJerome Glisse } 844771fe6b9SJerome Glisse 845f92a8b67SAlex Deucher if (is_dp) 846f92a8b67SAlex Deucher args.v2.acConfig.fCoherentMode = 1; 847f92a8b67SAlex Deucher else if (radeon_encoder->devices & (ATOM_DEVICE_DFP_SUPPORT)) { 848771fe6b9SJerome Glisse if (dig->coherent_mode) 849771fe6b9SJerome Glisse args.v2.acConfig.fCoherentMode = 1; 850771fe6b9SJerome Glisse } 851771fe6b9SJerome Glisse } else { 852771fe6b9SJerome Glisse args.v1.ucConfig = ATOM_TRANSMITTER_CONFIG_CLKSRC_PPLL; 853771fe6b9SJerome Glisse 854771fe6b9SJerome Glisse switch (radeon_encoder->encoder_id) { 855771fe6b9SJerome Glisse case ENCODER_OBJECT_ID_INTERNAL_UNIPHY: 8561a66c95aSAlex Deucher /* XXX doesn't really matter which dig encoder we pick as long as it's 8571a66c95aSAlex Deucher * not already in use 8581a66c95aSAlex Deucher */ 8591a66c95aSAlex Deucher if (dig_connector->linkb) 8601a66c95aSAlex Deucher args.v1.ucConfig |= ATOM_TRANSMITTER_CONFIG_DIG2_ENCODER; 8611a66c95aSAlex Deucher else 862771fe6b9SJerome Glisse args.v1.ucConfig |= ATOM_TRANSMITTER_CONFIG_DIG1_ENCODER; 863771fe6b9SJerome Glisse if (rdev->flags & RADEON_IS_IGP) { 864771fe6b9SJerome Glisse if (radeon_encoder->pixel_clock > 165000) { 865771fe6b9SJerome Glisse if (dig_connector->igp_lane_info & 0x3) 866771fe6b9SJerome Glisse args.v1.ucConfig |= ATOM_TRANSMITTER_CONFIG_LANE_0_7; 867771fe6b9SJerome Glisse else if (dig_connector->igp_lane_info & 0xc) 868771fe6b9SJerome Glisse args.v1.ucConfig |= ATOM_TRANSMITTER_CONFIG_LANE_8_15; 869771fe6b9SJerome Glisse } else { 870771fe6b9SJerome Glisse if (dig_connector->igp_lane_info & 0x1) 871771fe6b9SJerome Glisse args.v1.ucConfig |= ATOM_TRANSMITTER_CONFIG_LANE_0_3; 872771fe6b9SJerome Glisse else if (dig_connector->igp_lane_info & 0x2) 873771fe6b9SJerome Glisse args.v1.ucConfig |= ATOM_TRANSMITTER_CONFIG_LANE_4_7; 874771fe6b9SJerome Glisse else if (dig_connector->igp_lane_info & 0x4) 875771fe6b9SJerome Glisse args.v1.ucConfig |= ATOM_TRANSMITTER_CONFIG_LANE_8_11; 876771fe6b9SJerome Glisse else if (dig_connector->igp_lane_info & 0x8) 877771fe6b9SJerome Glisse args.v1.ucConfig |= ATOM_TRANSMITTER_CONFIG_LANE_12_15; 878771fe6b9SJerome Glisse } 879771fe6b9SJerome Glisse } 880771fe6b9SJerome Glisse break; 881771fe6b9SJerome Glisse case ENCODER_OBJECT_ID_INTERNAL_KLDSCP_LVTMA: 8821a66c95aSAlex Deucher /* Only dig2 encoder can drive LVTMA */ 883771fe6b9SJerome Glisse args.v1.ucConfig |= ATOM_TRANSMITTER_CONFIG_DIG2_ENCODER; 884771fe6b9SJerome Glisse break; 885771fe6b9SJerome Glisse } 886771fe6b9SJerome Glisse 8871a66c95aSAlex Deucher if (radeon_encoder->pixel_clock > 165000) 8881a66c95aSAlex Deucher args.v1.ucConfig |= ATOM_TRANSMITTER_CONFIG_8LANE_LINK; 8891a66c95aSAlex Deucher 8901a66c95aSAlex Deucher if (dig_connector->linkb) 8911a66c95aSAlex Deucher args.v1.ucConfig |= ATOM_TRANSMITTER_CONFIG_LINKB; 8921a66c95aSAlex Deucher else 8931a66c95aSAlex Deucher args.v1.ucConfig |= ATOM_TRANSMITTER_CONFIG_LINKA; 8941a66c95aSAlex Deucher 895f92a8b67SAlex Deucher if (is_dp) 896f92a8b67SAlex Deucher args.v1.ucConfig |= ATOM_TRANSMITTER_CONFIG_COHERENT; 897f92a8b67SAlex Deucher else if (radeon_encoder->devices & (ATOM_DEVICE_DFP_SUPPORT)) { 898771fe6b9SJerome Glisse if (dig->coherent_mode) 899771fe6b9SJerome Glisse args.v1.ucConfig |= ATOM_TRANSMITTER_CONFIG_COHERENT; 900771fe6b9SJerome Glisse } 901771fe6b9SJerome Glisse } 902771fe6b9SJerome Glisse 903771fe6b9SJerome Glisse atom_execute_table(rdev->mode_info.atom_context, index, (uint32_t *)&args); 904771fe6b9SJerome Glisse } 905771fe6b9SJerome Glisse 906771fe6b9SJerome Glisse static void 907771fe6b9SJerome Glisse atombios_yuv_setup(struct drm_encoder *encoder, bool enable) 908771fe6b9SJerome Glisse { 909771fe6b9SJerome Glisse struct drm_device *dev = encoder->dev; 910771fe6b9SJerome Glisse struct radeon_device *rdev = dev->dev_private; 911771fe6b9SJerome Glisse struct radeon_encoder *radeon_encoder = to_radeon_encoder(encoder); 912771fe6b9SJerome Glisse struct radeon_crtc *radeon_crtc = to_radeon_crtc(encoder->crtc); 913771fe6b9SJerome Glisse ENABLE_YUV_PS_ALLOCATION args; 914771fe6b9SJerome Glisse int index = GetIndexIntoMasterTable(COMMAND, EnableYUV); 915771fe6b9SJerome Glisse uint32_t temp, reg; 916771fe6b9SJerome Glisse 917771fe6b9SJerome Glisse memset(&args, 0, sizeof(args)); 918771fe6b9SJerome Glisse 919771fe6b9SJerome Glisse if (rdev->family >= CHIP_R600) 920771fe6b9SJerome Glisse reg = R600_BIOS_3_SCRATCH; 921771fe6b9SJerome Glisse else 922771fe6b9SJerome Glisse reg = RADEON_BIOS_3_SCRATCH; 923771fe6b9SJerome Glisse 924771fe6b9SJerome Glisse /* XXX: fix up scratch reg handling */ 925771fe6b9SJerome Glisse temp = RREG32(reg); 9264ce001abSDave Airlie if (radeon_encoder->active_device & (ATOM_DEVICE_TV_SUPPORT)) 927771fe6b9SJerome Glisse WREG32(reg, (ATOM_S3_TV1_ACTIVE | 928771fe6b9SJerome Glisse (radeon_crtc->crtc_id << 18))); 9294ce001abSDave Airlie else if (radeon_encoder->active_device & (ATOM_DEVICE_CV_SUPPORT)) 930771fe6b9SJerome Glisse WREG32(reg, (ATOM_S3_CV_ACTIVE | (radeon_crtc->crtc_id << 24))); 931771fe6b9SJerome Glisse else 932771fe6b9SJerome Glisse WREG32(reg, 0); 933771fe6b9SJerome Glisse 934771fe6b9SJerome Glisse if (enable) 935771fe6b9SJerome Glisse args.ucEnable = ATOM_ENABLE; 936771fe6b9SJerome Glisse args.ucCRTC = radeon_crtc->crtc_id; 937771fe6b9SJerome Glisse 938771fe6b9SJerome Glisse atom_execute_table(rdev->mode_info.atom_context, index, (uint32_t *)&args); 939771fe6b9SJerome Glisse 940771fe6b9SJerome Glisse WREG32(reg, temp); 941771fe6b9SJerome Glisse } 942771fe6b9SJerome Glisse 943771fe6b9SJerome Glisse static void 944771fe6b9SJerome Glisse radeon_atom_encoder_dpms(struct drm_encoder *encoder, int mode) 945771fe6b9SJerome Glisse { 946771fe6b9SJerome Glisse struct drm_device *dev = encoder->dev; 947771fe6b9SJerome Glisse struct radeon_device *rdev = dev->dev_private; 948771fe6b9SJerome Glisse struct radeon_encoder *radeon_encoder = to_radeon_encoder(encoder); 949771fe6b9SJerome Glisse DISPLAY_DEVICE_OUTPUT_CONTROL_PS_ALLOCATION args; 950771fe6b9SJerome Glisse int index = 0; 951771fe6b9SJerome Glisse bool is_dig = false; 952771fe6b9SJerome Glisse 953771fe6b9SJerome Glisse memset(&args, 0, sizeof(args)); 954771fe6b9SJerome Glisse 955f641e51eSDave Airlie DRM_DEBUG("encoder dpms %d to mode %d, devices %08x, active_devices %08x\n", 9564ce001abSDave Airlie radeon_encoder->encoder_id, mode, radeon_encoder->devices, 9574ce001abSDave Airlie radeon_encoder->active_device); 958771fe6b9SJerome Glisse switch (radeon_encoder->encoder_id) { 959771fe6b9SJerome Glisse case ENCODER_OBJECT_ID_INTERNAL_TMDS1: 960771fe6b9SJerome Glisse case ENCODER_OBJECT_ID_INTERNAL_KLDSCP_TMDS1: 961771fe6b9SJerome Glisse index = GetIndexIntoMasterTable(COMMAND, TMDSAOutputControl); 962771fe6b9SJerome Glisse break; 963771fe6b9SJerome Glisse case ENCODER_OBJECT_ID_INTERNAL_UNIPHY: 964771fe6b9SJerome Glisse case ENCODER_OBJECT_ID_INTERNAL_UNIPHY1: 965771fe6b9SJerome Glisse case ENCODER_OBJECT_ID_INTERNAL_UNIPHY2: 966771fe6b9SJerome Glisse case ENCODER_OBJECT_ID_INTERNAL_KLDSCP_LVTMA: 967771fe6b9SJerome Glisse is_dig = true; 968771fe6b9SJerome Glisse break; 969771fe6b9SJerome Glisse case ENCODER_OBJECT_ID_INTERNAL_DVO1: 970771fe6b9SJerome Glisse case ENCODER_OBJECT_ID_INTERNAL_DDI: 971771fe6b9SJerome Glisse case ENCODER_OBJECT_ID_INTERNAL_KLDSCP_DVO1: 972771fe6b9SJerome Glisse index = GetIndexIntoMasterTable(COMMAND, DVOOutputControl); 973771fe6b9SJerome Glisse break; 974771fe6b9SJerome Glisse case ENCODER_OBJECT_ID_INTERNAL_LVDS: 975771fe6b9SJerome Glisse index = GetIndexIntoMasterTable(COMMAND, LCD1OutputControl); 976771fe6b9SJerome Glisse break; 977771fe6b9SJerome Glisse case ENCODER_OBJECT_ID_INTERNAL_LVTM1: 978771fe6b9SJerome Glisse if (radeon_encoder->devices & (ATOM_DEVICE_LCD_SUPPORT)) 979771fe6b9SJerome Glisse index = GetIndexIntoMasterTable(COMMAND, LCD1OutputControl); 980771fe6b9SJerome Glisse else 981771fe6b9SJerome Glisse index = GetIndexIntoMasterTable(COMMAND, LVTMAOutputControl); 982771fe6b9SJerome Glisse break; 983771fe6b9SJerome Glisse case ENCODER_OBJECT_ID_INTERNAL_DAC1: 984771fe6b9SJerome Glisse case ENCODER_OBJECT_ID_INTERNAL_KLDSCP_DAC1: 9858c2a6d73SAlex Deucher if (radeon_encoder->active_device & (ATOM_DEVICE_TV_SUPPORT)) 986771fe6b9SJerome Glisse index = GetIndexIntoMasterTable(COMMAND, TV1OutputControl); 9878c2a6d73SAlex Deucher else if (radeon_encoder->active_device & (ATOM_DEVICE_CV_SUPPORT)) 988771fe6b9SJerome Glisse index = GetIndexIntoMasterTable(COMMAND, CV1OutputControl); 989771fe6b9SJerome Glisse else 990771fe6b9SJerome Glisse index = GetIndexIntoMasterTable(COMMAND, DAC1OutputControl); 991771fe6b9SJerome Glisse break; 992771fe6b9SJerome Glisse case ENCODER_OBJECT_ID_INTERNAL_DAC2: 993771fe6b9SJerome Glisse case ENCODER_OBJECT_ID_INTERNAL_KLDSCP_DAC2: 9948c2a6d73SAlex Deucher if (radeon_encoder->active_device & (ATOM_DEVICE_TV_SUPPORT)) 995771fe6b9SJerome Glisse index = GetIndexIntoMasterTable(COMMAND, TV1OutputControl); 9968c2a6d73SAlex Deucher else if (radeon_encoder->active_device & (ATOM_DEVICE_CV_SUPPORT)) 997771fe6b9SJerome Glisse index = GetIndexIntoMasterTable(COMMAND, CV1OutputControl); 998771fe6b9SJerome Glisse else 999771fe6b9SJerome Glisse index = GetIndexIntoMasterTable(COMMAND, DAC2OutputControl); 1000771fe6b9SJerome Glisse break; 1001771fe6b9SJerome Glisse } 1002771fe6b9SJerome Glisse 1003771fe6b9SJerome Glisse if (is_dig) { 1004771fe6b9SJerome Glisse switch (mode) { 1005771fe6b9SJerome Glisse case DRM_MODE_DPMS_ON: 100658682f10SDave Airlie atombios_dig_transmitter_setup(encoder, ATOM_TRANSMITTER_ACTION_ENABLE_OUTPUT, 0, 0); 100758682f10SDave Airlie { 100858682f10SDave Airlie struct drm_connector *connector = radeon_get_connector_for_encoder(encoder); 100958682f10SDave Airlie dp_link_train(encoder, connector); 101058682f10SDave Airlie } 1011771fe6b9SJerome Glisse break; 1012771fe6b9SJerome Glisse case DRM_MODE_DPMS_STANDBY: 1013771fe6b9SJerome Glisse case DRM_MODE_DPMS_SUSPEND: 1014771fe6b9SJerome Glisse case DRM_MODE_DPMS_OFF: 101558682f10SDave Airlie atombios_dig_transmitter_setup(encoder, ATOM_TRANSMITTER_ACTION_DISABLE_OUTPUT, 0, 0); 1016771fe6b9SJerome Glisse break; 1017771fe6b9SJerome Glisse } 1018771fe6b9SJerome Glisse } else { 1019771fe6b9SJerome Glisse switch (mode) { 1020771fe6b9SJerome Glisse case DRM_MODE_DPMS_ON: 1021771fe6b9SJerome Glisse args.ucAction = ATOM_ENABLE; 1022771fe6b9SJerome Glisse break; 1023771fe6b9SJerome Glisse case DRM_MODE_DPMS_STANDBY: 1024771fe6b9SJerome Glisse case DRM_MODE_DPMS_SUSPEND: 1025771fe6b9SJerome Glisse case DRM_MODE_DPMS_OFF: 1026771fe6b9SJerome Glisse args.ucAction = ATOM_DISABLE; 1027771fe6b9SJerome Glisse break; 1028771fe6b9SJerome Glisse } 1029771fe6b9SJerome Glisse atom_execute_table(rdev->mode_info.atom_context, index, (uint32_t *)&args); 1030771fe6b9SJerome Glisse } 1031771fe6b9SJerome Glisse radeon_atombios_encoder_dpms_scratch_regs(encoder, (mode == DRM_MODE_DPMS_ON) ? true : false); 1032771fe6b9SJerome Glisse } 1033771fe6b9SJerome Glisse 1034771fe6b9SJerome Glisse union crtc_sourc_param { 1035771fe6b9SJerome Glisse SELECT_CRTC_SOURCE_PS_ALLOCATION v1; 1036771fe6b9SJerome Glisse SELECT_CRTC_SOURCE_PARAMETERS_V2 v2; 1037771fe6b9SJerome Glisse }; 1038771fe6b9SJerome Glisse 1039771fe6b9SJerome Glisse static void 1040771fe6b9SJerome Glisse atombios_set_encoder_crtc_source(struct drm_encoder *encoder) 1041771fe6b9SJerome Glisse { 1042771fe6b9SJerome Glisse struct drm_device *dev = encoder->dev; 1043771fe6b9SJerome Glisse struct radeon_device *rdev = dev->dev_private; 1044771fe6b9SJerome Glisse struct radeon_encoder *radeon_encoder = to_radeon_encoder(encoder); 1045771fe6b9SJerome Glisse struct radeon_crtc *radeon_crtc = to_radeon_crtc(encoder->crtc); 1046771fe6b9SJerome Glisse union crtc_sourc_param args; 1047771fe6b9SJerome Glisse int index = GetIndexIntoMasterTable(COMMAND, SelectCRTC_Source); 1048771fe6b9SJerome Glisse uint8_t frev, crev; 1049771fe6b9SJerome Glisse 1050771fe6b9SJerome Glisse memset(&args, 0, sizeof(args)); 1051771fe6b9SJerome Glisse 1052771fe6b9SJerome Glisse atom_parse_cmd_header(rdev->mode_info.atom_context, index, &frev, &crev); 1053771fe6b9SJerome Glisse 1054771fe6b9SJerome Glisse switch (frev) { 1055771fe6b9SJerome Glisse case 1: 1056771fe6b9SJerome Glisse switch (crev) { 1057771fe6b9SJerome Glisse case 1: 1058771fe6b9SJerome Glisse default: 1059771fe6b9SJerome Glisse if (ASIC_IS_AVIVO(rdev)) 1060771fe6b9SJerome Glisse args.v1.ucCRTC = radeon_crtc->crtc_id; 1061771fe6b9SJerome Glisse else { 1062771fe6b9SJerome Glisse if (radeon_encoder->encoder_id == ENCODER_OBJECT_ID_INTERNAL_DAC1) { 1063771fe6b9SJerome Glisse args.v1.ucCRTC = radeon_crtc->crtc_id; 1064771fe6b9SJerome Glisse } else { 1065771fe6b9SJerome Glisse args.v1.ucCRTC = radeon_crtc->crtc_id << 2; 1066771fe6b9SJerome Glisse } 1067771fe6b9SJerome Glisse } 1068771fe6b9SJerome Glisse switch (radeon_encoder->encoder_id) { 1069771fe6b9SJerome Glisse case ENCODER_OBJECT_ID_INTERNAL_TMDS1: 1070771fe6b9SJerome Glisse case ENCODER_OBJECT_ID_INTERNAL_KLDSCP_TMDS1: 1071771fe6b9SJerome Glisse args.v1.ucDevice = ATOM_DEVICE_DFP1_INDEX; 1072771fe6b9SJerome Glisse break; 1073771fe6b9SJerome Glisse case ENCODER_OBJECT_ID_INTERNAL_LVDS: 1074771fe6b9SJerome Glisse case ENCODER_OBJECT_ID_INTERNAL_LVTM1: 1075771fe6b9SJerome Glisse if (radeon_encoder->devices & ATOM_DEVICE_LCD1_SUPPORT) 1076771fe6b9SJerome Glisse args.v1.ucDevice = ATOM_DEVICE_LCD1_INDEX; 1077771fe6b9SJerome Glisse else 1078771fe6b9SJerome Glisse args.v1.ucDevice = ATOM_DEVICE_DFP3_INDEX; 1079771fe6b9SJerome Glisse break; 1080771fe6b9SJerome Glisse case ENCODER_OBJECT_ID_INTERNAL_DVO1: 1081771fe6b9SJerome Glisse case ENCODER_OBJECT_ID_INTERNAL_DDI: 1082771fe6b9SJerome Glisse case ENCODER_OBJECT_ID_INTERNAL_KLDSCP_DVO1: 1083771fe6b9SJerome Glisse args.v1.ucDevice = ATOM_DEVICE_DFP2_INDEX; 1084771fe6b9SJerome Glisse break; 1085771fe6b9SJerome Glisse case ENCODER_OBJECT_ID_INTERNAL_DAC1: 1086771fe6b9SJerome Glisse case ENCODER_OBJECT_ID_INTERNAL_KLDSCP_DAC1: 10874ce001abSDave Airlie if (radeon_encoder->active_device & (ATOM_DEVICE_TV_SUPPORT)) 1088771fe6b9SJerome Glisse args.v1.ucDevice = ATOM_DEVICE_TV1_INDEX; 10894ce001abSDave Airlie else if (radeon_encoder->active_device & (ATOM_DEVICE_CV_SUPPORT)) 1090771fe6b9SJerome Glisse args.v1.ucDevice = ATOM_DEVICE_CV_INDEX; 1091771fe6b9SJerome Glisse else 1092771fe6b9SJerome Glisse args.v1.ucDevice = ATOM_DEVICE_CRT1_INDEX; 1093771fe6b9SJerome Glisse break; 1094771fe6b9SJerome Glisse case ENCODER_OBJECT_ID_INTERNAL_DAC2: 1095771fe6b9SJerome Glisse case ENCODER_OBJECT_ID_INTERNAL_KLDSCP_DAC2: 10964ce001abSDave Airlie if (radeon_encoder->active_device & (ATOM_DEVICE_TV_SUPPORT)) 1097771fe6b9SJerome Glisse args.v1.ucDevice = ATOM_DEVICE_TV1_INDEX; 10984ce001abSDave Airlie else if (radeon_encoder->active_device & (ATOM_DEVICE_CV_SUPPORT)) 1099771fe6b9SJerome Glisse args.v1.ucDevice = ATOM_DEVICE_CV_INDEX; 1100771fe6b9SJerome Glisse else 1101771fe6b9SJerome Glisse args.v1.ucDevice = ATOM_DEVICE_CRT2_INDEX; 1102771fe6b9SJerome Glisse break; 1103771fe6b9SJerome Glisse } 1104771fe6b9SJerome Glisse break; 1105771fe6b9SJerome Glisse case 2: 1106771fe6b9SJerome Glisse args.v2.ucCRTC = radeon_crtc->crtc_id; 1107771fe6b9SJerome Glisse args.v2.ucEncodeMode = atombios_get_encoder_mode(encoder); 1108771fe6b9SJerome Glisse switch (radeon_encoder->encoder_id) { 1109771fe6b9SJerome Glisse case ENCODER_OBJECT_ID_INTERNAL_UNIPHY: 1110771fe6b9SJerome Glisse case ENCODER_OBJECT_ID_INTERNAL_UNIPHY1: 1111771fe6b9SJerome Glisse case ENCODER_OBJECT_ID_INTERNAL_UNIPHY2: 1112771fe6b9SJerome Glisse if (ASIC_IS_DCE32(rdev)) { 1113771fe6b9SJerome Glisse if (radeon_crtc->crtc_id) 1114771fe6b9SJerome Glisse args.v2.ucEncoderID = ASIC_INT_DIG2_ENCODER_ID; 1115771fe6b9SJerome Glisse else 1116771fe6b9SJerome Glisse args.v2.ucEncoderID = ASIC_INT_DIG1_ENCODER_ID; 11171a66c95aSAlex Deucher } else { 11181a66c95aSAlex Deucher struct drm_connector *connector; 11191a66c95aSAlex Deucher struct radeon_connector *radeon_connector; 11201a66c95aSAlex Deucher struct radeon_connector_atom_dig *dig_connector; 11211a66c95aSAlex Deucher 11221a66c95aSAlex Deucher connector = radeon_get_connector_for_encoder(encoder); 11231a66c95aSAlex Deucher if (!connector) 11241a66c95aSAlex Deucher return; 11251a66c95aSAlex Deucher radeon_connector = to_radeon_connector(connector); 11261a66c95aSAlex Deucher if (!radeon_connector->con_priv) 11271a66c95aSAlex Deucher return; 11281a66c95aSAlex Deucher dig_connector = radeon_connector->con_priv; 11291a66c95aSAlex Deucher 11301a66c95aSAlex Deucher /* XXX doesn't really matter which dig encoder we pick as long as it's 11311a66c95aSAlex Deucher * not already in use 11321a66c95aSAlex Deucher */ 11331a66c95aSAlex Deucher if (dig_connector->linkb) 11341a66c95aSAlex Deucher args.v2.ucEncoderID = ASIC_INT_DIG2_ENCODER_ID; 11351a66c95aSAlex Deucher else 1136771fe6b9SJerome Glisse args.v2.ucEncoderID = ASIC_INT_DIG1_ENCODER_ID; 11371a66c95aSAlex Deucher } 1138771fe6b9SJerome Glisse break; 1139771fe6b9SJerome Glisse case ENCODER_OBJECT_ID_INTERNAL_KLDSCP_DVO1: 1140771fe6b9SJerome Glisse args.v2.ucEncoderID = ASIC_INT_DVO_ENCODER_ID; 1141771fe6b9SJerome Glisse break; 1142771fe6b9SJerome Glisse case ENCODER_OBJECT_ID_INTERNAL_KLDSCP_LVTMA: 11431a66c95aSAlex Deucher /* Only dig2 encoder can drive LVTMA */ 1144771fe6b9SJerome Glisse args.v2.ucEncoderID = ASIC_INT_DIG2_ENCODER_ID; 1145771fe6b9SJerome Glisse break; 1146771fe6b9SJerome Glisse case ENCODER_OBJECT_ID_INTERNAL_KLDSCP_DAC1: 11474ce001abSDave Airlie if (radeon_encoder->active_device & (ATOM_DEVICE_TV_SUPPORT)) 1148771fe6b9SJerome Glisse args.v2.ucEncoderID = ASIC_INT_TV_ENCODER_ID; 11494ce001abSDave Airlie else if (radeon_encoder->active_device & (ATOM_DEVICE_CV_SUPPORT)) 1150771fe6b9SJerome Glisse args.v2.ucEncoderID = ASIC_INT_TV_ENCODER_ID; 1151771fe6b9SJerome Glisse else 1152771fe6b9SJerome Glisse args.v2.ucEncoderID = ASIC_INT_DAC1_ENCODER_ID; 1153771fe6b9SJerome Glisse break; 1154771fe6b9SJerome Glisse case ENCODER_OBJECT_ID_INTERNAL_KLDSCP_DAC2: 11554ce001abSDave Airlie if (radeon_encoder->active_device & (ATOM_DEVICE_TV_SUPPORT)) 1156771fe6b9SJerome Glisse args.v2.ucEncoderID = ASIC_INT_TV_ENCODER_ID; 11574ce001abSDave Airlie else if (radeon_encoder->active_device & (ATOM_DEVICE_CV_SUPPORT)) 1158771fe6b9SJerome Glisse args.v2.ucEncoderID = ASIC_INT_TV_ENCODER_ID; 1159771fe6b9SJerome Glisse else 1160771fe6b9SJerome Glisse args.v2.ucEncoderID = ASIC_INT_DAC2_ENCODER_ID; 1161771fe6b9SJerome Glisse break; 1162771fe6b9SJerome Glisse } 1163771fe6b9SJerome Glisse break; 1164771fe6b9SJerome Glisse } 1165771fe6b9SJerome Glisse break; 1166771fe6b9SJerome Glisse default: 1167771fe6b9SJerome Glisse DRM_ERROR("Unknown table version: %d, %d\n", frev, crev); 1168771fe6b9SJerome Glisse break; 1169771fe6b9SJerome Glisse } 1170771fe6b9SJerome Glisse 1171771fe6b9SJerome Glisse atom_execute_table(rdev->mode_info.atom_context, index, (uint32_t *)&args); 1172771fe6b9SJerome Glisse } 1173771fe6b9SJerome Glisse 1174771fe6b9SJerome Glisse static void 1175771fe6b9SJerome Glisse atombios_apply_encoder_quirks(struct drm_encoder *encoder, 1176771fe6b9SJerome Glisse struct drm_display_mode *mode) 1177771fe6b9SJerome Glisse { 1178771fe6b9SJerome Glisse struct drm_device *dev = encoder->dev; 1179771fe6b9SJerome Glisse struct radeon_device *rdev = dev->dev_private; 1180771fe6b9SJerome Glisse struct radeon_encoder *radeon_encoder = to_radeon_encoder(encoder); 1181771fe6b9SJerome Glisse struct radeon_crtc *radeon_crtc = to_radeon_crtc(encoder->crtc); 1182771fe6b9SJerome Glisse 1183771fe6b9SJerome Glisse /* Funky macbooks */ 1184771fe6b9SJerome Glisse if ((dev->pdev->device == 0x71C5) && 1185771fe6b9SJerome Glisse (dev->pdev->subsystem_vendor == 0x106b) && 1186771fe6b9SJerome Glisse (dev->pdev->subsystem_device == 0x0080)) { 1187771fe6b9SJerome Glisse if (radeon_encoder->devices & ATOM_DEVICE_LCD1_SUPPORT) { 1188771fe6b9SJerome Glisse uint32_t lvtma_bit_depth_control = RREG32(AVIVO_LVTMA_BIT_DEPTH_CONTROL); 1189771fe6b9SJerome Glisse 1190771fe6b9SJerome Glisse lvtma_bit_depth_control &= ~AVIVO_LVTMA_BIT_DEPTH_CONTROL_TRUNCATE_EN; 1191771fe6b9SJerome Glisse lvtma_bit_depth_control &= ~AVIVO_LVTMA_BIT_DEPTH_CONTROL_SPATIAL_DITHER_EN; 1192771fe6b9SJerome Glisse 1193771fe6b9SJerome Glisse WREG32(AVIVO_LVTMA_BIT_DEPTH_CONTROL, lvtma_bit_depth_control); 1194771fe6b9SJerome Glisse } 1195771fe6b9SJerome Glisse } 1196771fe6b9SJerome Glisse 1197771fe6b9SJerome Glisse /* set scaler clears this on some chips */ 1198ceefedd8SAlex Deucher if (!(radeon_encoder->active_device & (ATOM_DEVICE_TV_SUPPORT))) { 1199771fe6b9SJerome Glisse if (ASIC_IS_AVIVO(rdev) && (mode->flags & DRM_MODE_FLAG_INTERLACE)) 1200ceefedd8SAlex Deucher WREG32(AVIVO_D1MODE_DATA_FORMAT + radeon_crtc->crtc_offset, 1201ceefedd8SAlex Deucher AVIVO_D1MODE_INTERLEAVE_EN); 1202ceefedd8SAlex Deucher } 1203771fe6b9SJerome Glisse } 1204771fe6b9SJerome Glisse 1205771fe6b9SJerome Glisse static void 1206771fe6b9SJerome Glisse radeon_atom_encoder_mode_set(struct drm_encoder *encoder, 1207771fe6b9SJerome Glisse struct drm_display_mode *mode, 1208771fe6b9SJerome Glisse struct drm_display_mode *adjusted_mode) 1209771fe6b9SJerome Glisse { 1210771fe6b9SJerome Glisse struct drm_device *dev = encoder->dev; 1211771fe6b9SJerome Glisse struct radeon_device *rdev = dev->dev_private; 1212771fe6b9SJerome Glisse struct radeon_encoder *radeon_encoder = to_radeon_encoder(encoder); 1213771fe6b9SJerome Glisse struct radeon_crtc *radeon_crtc = to_radeon_crtc(encoder->crtc); 1214771fe6b9SJerome Glisse 12155801ead6SAlex Deucher if (radeon_encoder->active_device & 12165801ead6SAlex Deucher (ATOM_DEVICE_DFP_SUPPORT | ATOM_DEVICE_LCD_SUPPORT)) { 1217771fe6b9SJerome Glisse if (radeon_encoder->enc_priv) { 1218771fe6b9SJerome Glisse struct radeon_encoder_atom_dig *dig; 1219771fe6b9SJerome Glisse 1220771fe6b9SJerome Glisse dig = radeon_encoder->enc_priv; 1221771fe6b9SJerome Glisse dig->dig_block = radeon_crtc->crtc_id; 1222771fe6b9SJerome Glisse } 12235801ead6SAlex Deucher } 1224771fe6b9SJerome Glisse radeon_encoder->pixel_clock = adjusted_mode->clock; 1225771fe6b9SJerome Glisse 1226771fe6b9SJerome Glisse radeon_atombios_encoder_crtc_scratch_regs(encoder, radeon_crtc->crtc_id); 1227771fe6b9SJerome Glisse atombios_set_encoder_crtc_source(encoder); 1228771fe6b9SJerome Glisse 1229771fe6b9SJerome Glisse if (ASIC_IS_AVIVO(rdev)) { 12304ce001abSDave Airlie if (radeon_encoder->active_device & (ATOM_DEVICE_CV_SUPPORT | ATOM_DEVICE_TV_SUPPORT)) 1231771fe6b9SJerome Glisse atombios_yuv_setup(encoder, true); 1232771fe6b9SJerome Glisse else 1233771fe6b9SJerome Glisse atombios_yuv_setup(encoder, false); 1234771fe6b9SJerome Glisse } 1235771fe6b9SJerome Glisse 1236771fe6b9SJerome Glisse switch (radeon_encoder->encoder_id) { 1237771fe6b9SJerome Glisse case ENCODER_OBJECT_ID_INTERNAL_TMDS1: 1238771fe6b9SJerome Glisse case ENCODER_OBJECT_ID_INTERNAL_KLDSCP_TMDS1: 1239771fe6b9SJerome Glisse case ENCODER_OBJECT_ID_INTERNAL_LVDS: 1240771fe6b9SJerome Glisse case ENCODER_OBJECT_ID_INTERNAL_LVTM1: 1241771fe6b9SJerome Glisse atombios_digital_setup(encoder, PANEL_ENCODER_ACTION_ENABLE); 1242771fe6b9SJerome Glisse break; 1243771fe6b9SJerome Glisse case ENCODER_OBJECT_ID_INTERNAL_UNIPHY: 1244771fe6b9SJerome Glisse case ENCODER_OBJECT_ID_INTERNAL_UNIPHY1: 1245771fe6b9SJerome Glisse case ENCODER_OBJECT_ID_INTERNAL_UNIPHY2: 1246771fe6b9SJerome Glisse case ENCODER_OBJECT_ID_INTERNAL_KLDSCP_LVTMA: 1247771fe6b9SJerome Glisse /* disable the encoder and transmitter */ 12481a66c95aSAlex Deucher atombios_dig_transmitter_setup(encoder, ATOM_TRANSMITTER_ACTION_DISABLE, 0, 0); 1249771fe6b9SJerome Glisse atombios_dig_encoder_setup(encoder, ATOM_DISABLE); 1250771fe6b9SJerome Glisse 1251771fe6b9SJerome Glisse /* setup and enable the encoder and transmitter */ 1252771fe6b9SJerome Glisse atombios_dig_encoder_setup(encoder, ATOM_ENABLE); 12531a66c95aSAlex Deucher atombios_dig_transmitter_setup(encoder, ATOM_TRANSMITTER_ACTION_INIT, 0, 0); 12541a66c95aSAlex Deucher atombios_dig_transmitter_setup(encoder, ATOM_TRANSMITTER_ACTION_SETUP, 0, 0); 12551a66c95aSAlex Deucher atombios_dig_transmitter_setup(encoder, ATOM_TRANSMITTER_ACTION_ENABLE, 0, 0); 1256771fe6b9SJerome Glisse break; 1257771fe6b9SJerome Glisse case ENCODER_OBJECT_ID_INTERNAL_DDI: 1258771fe6b9SJerome Glisse atombios_ddia_setup(encoder, ATOM_ENABLE); 1259771fe6b9SJerome Glisse break; 1260771fe6b9SJerome Glisse case ENCODER_OBJECT_ID_INTERNAL_DVO1: 1261771fe6b9SJerome Glisse case ENCODER_OBJECT_ID_INTERNAL_KLDSCP_DVO1: 1262771fe6b9SJerome Glisse atombios_external_tmds_setup(encoder, ATOM_ENABLE); 1263771fe6b9SJerome Glisse break; 1264771fe6b9SJerome Glisse case ENCODER_OBJECT_ID_INTERNAL_DAC1: 1265771fe6b9SJerome Glisse case ENCODER_OBJECT_ID_INTERNAL_KLDSCP_DAC1: 1266771fe6b9SJerome Glisse case ENCODER_OBJECT_ID_INTERNAL_DAC2: 1267771fe6b9SJerome Glisse case ENCODER_OBJECT_ID_INTERNAL_KLDSCP_DAC2: 1268771fe6b9SJerome Glisse atombios_dac_setup(encoder, ATOM_ENABLE); 12694ce001abSDave Airlie if (radeon_encoder->active_device & (ATOM_DEVICE_TV_SUPPORT | ATOM_DEVICE_CV_SUPPORT)) 1270771fe6b9SJerome Glisse atombios_tv_setup(encoder, ATOM_ENABLE); 1271771fe6b9SJerome Glisse break; 1272771fe6b9SJerome Glisse } 1273771fe6b9SJerome Glisse atombios_apply_encoder_quirks(encoder, adjusted_mode); 1274dafc3bd5SChristian Koenig 1275dafc3bd5SChristian Koenig r600_hdmi_setmode(encoder, adjusted_mode); 1276771fe6b9SJerome Glisse } 1277771fe6b9SJerome Glisse 1278771fe6b9SJerome Glisse static bool 12794ce001abSDave Airlie atombios_dac_load_detect(struct drm_encoder *encoder, struct drm_connector *connector) 1280771fe6b9SJerome Glisse { 1281771fe6b9SJerome Glisse struct drm_device *dev = encoder->dev; 1282771fe6b9SJerome Glisse struct radeon_device *rdev = dev->dev_private; 1283771fe6b9SJerome Glisse struct radeon_encoder *radeon_encoder = to_radeon_encoder(encoder); 12844ce001abSDave Airlie struct radeon_connector *radeon_connector = to_radeon_connector(connector); 1285771fe6b9SJerome Glisse 1286771fe6b9SJerome Glisse if (radeon_encoder->devices & (ATOM_DEVICE_TV_SUPPORT | 1287771fe6b9SJerome Glisse ATOM_DEVICE_CV_SUPPORT | 1288771fe6b9SJerome Glisse ATOM_DEVICE_CRT_SUPPORT)) { 1289771fe6b9SJerome Glisse DAC_LOAD_DETECTION_PS_ALLOCATION args; 1290771fe6b9SJerome Glisse int index = GetIndexIntoMasterTable(COMMAND, DAC_LoadDetection); 1291771fe6b9SJerome Glisse uint8_t frev, crev; 1292771fe6b9SJerome Glisse 1293771fe6b9SJerome Glisse memset(&args, 0, sizeof(args)); 1294771fe6b9SJerome Glisse 1295771fe6b9SJerome Glisse atom_parse_cmd_header(rdev->mode_info.atom_context, index, &frev, &crev); 1296771fe6b9SJerome Glisse 1297771fe6b9SJerome Glisse args.sDacload.ucMisc = 0; 1298771fe6b9SJerome Glisse 1299771fe6b9SJerome Glisse if ((radeon_encoder->encoder_id == ENCODER_OBJECT_ID_INTERNAL_DAC1) || 1300771fe6b9SJerome Glisse (radeon_encoder->encoder_id == ENCODER_OBJECT_ID_INTERNAL_KLDSCP_DAC1)) 1301771fe6b9SJerome Glisse args.sDacload.ucDacType = ATOM_DAC_A; 1302771fe6b9SJerome Glisse else 1303771fe6b9SJerome Glisse args.sDacload.ucDacType = ATOM_DAC_B; 1304771fe6b9SJerome Glisse 13054ce001abSDave Airlie if (radeon_connector->devices & ATOM_DEVICE_CRT1_SUPPORT) 1306771fe6b9SJerome Glisse args.sDacload.usDeviceID = cpu_to_le16(ATOM_DEVICE_CRT1_SUPPORT); 13074ce001abSDave Airlie else if (radeon_connector->devices & ATOM_DEVICE_CRT2_SUPPORT) 1308771fe6b9SJerome Glisse args.sDacload.usDeviceID = cpu_to_le16(ATOM_DEVICE_CRT2_SUPPORT); 13094ce001abSDave Airlie else if (radeon_connector->devices & ATOM_DEVICE_CV_SUPPORT) { 1310771fe6b9SJerome Glisse args.sDacload.usDeviceID = cpu_to_le16(ATOM_DEVICE_CV_SUPPORT); 1311771fe6b9SJerome Glisse if (crev >= 3) 1312771fe6b9SJerome Glisse args.sDacload.ucMisc = DAC_LOAD_MISC_YPrPb; 13134ce001abSDave Airlie } else if (radeon_connector->devices & ATOM_DEVICE_TV1_SUPPORT) { 1314771fe6b9SJerome Glisse args.sDacload.usDeviceID = cpu_to_le16(ATOM_DEVICE_TV1_SUPPORT); 1315771fe6b9SJerome Glisse if (crev >= 3) 1316771fe6b9SJerome Glisse args.sDacload.ucMisc = DAC_LOAD_MISC_YPrPb; 1317771fe6b9SJerome Glisse } 1318771fe6b9SJerome Glisse 1319771fe6b9SJerome Glisse atom_execute_table(rdev->mode_info.atom_context, index, (uint32_t *)&args); 1320771fe6b9SJerome Glisse 1321771fe6b9SJerome Glisse return true; 1322771fe6b9SJerome Glisse } else 1323771fe6b9SJerome Glisse return false; 1324771fe6b9SJerome Glisse } 1325771fe6b9SJerome Glisse 1326771fe6b9SJerome Glisse static enum drm_connector_status 1327771fe6b9SJerome Glisse radeon_atom_dac_detect(struct drm_encoder *encoder, struct drm_connector *connector) 1328771fe6b9SJerome Glisse { 1329771fe6b9SJerome Glisse struct drm_device *dev = encoder->dev; 1330771fe6b9SJerome Glisse struct radeon_device *rdev = dev->dev_private; 1331771fe6b9SJerome Glisse struct radeon_encoder *radeon_encoder = to_radeon_encoder(encoder); 13324ce001abSDave Airlie struct radeon_connector *radeon_connector = to_radeon_connector(connector); 1333771fe6b9SJerome Glisse uint32_t bios_0_scratch; 1334771fe6b9SJerome Glisse 13354ce001abSDave Airlie if (!atombios_dac_load_detect(encoder, connector)) { 1336771fe6b9SJerome Glisse DRM_DEBUG("detect returned false \n"); 1337771fe6b9SJerome Glisse return connector_status_unknown; 1338771fe6b9SJerome Glisse } 1339771fe6b9SJerome Glisse 1340771fe6b9SJerome Glisse if (rdev->family >= CHIP_R600) 1341771fe6b9SJerome Glisse bios_0_scratch = RREG32(R600_BIOS_0_SCRATCH); 1342771fe6b9SJerome Glisse else 1343771fe6b9SJerome Glisse bios_0_scratch = RREG32(RADEON_BIOS_0_SCRATCH); 1344771fe6b9SJerome Glisse 13454ce001abSDave Airlie DRM_DEBUG("Bios 0 scratch %x %08x\n", bios_0_scratch, radeon_encoder->devices); 13464ce001abSDave Airlie if (radeon_connector->devices & ATOM_DEVICE_CRT1_SUPPORT) { 1347771fe6b9SJerome Glisse if (bios_0_scratch & ATOM_S0_CRT1_MASK) 1348771fe6b9SJerome Glisse return connector_status_connected; 13494ce001abSDave Airlie } 13504ce001abSDave Airlie if (radeon_connector->devices & ATOM_DEVICE_CRT2_SUPPORT) { 1351771fe6b9SJerome Glisse if (bios_0_scratch & ATOM_S0_CRT2_MASK) 1352771fe6b9SJerome Glisse return connector_status_connected; 13534ce001abSDave Airlie } 13544ce001abSDave Airlie if (radeon_connector->devices & ATOM_DEVICE_CV_SUPPORT) { 1355771fe6b9SJerome Glisse if (bios_0_scratch & (ATOM_S0_CV_MASK|ATOM_S0_CV_MASK_A)) 1356771fe6b9SJerome Glisse return connector_status_connected; 13574ce001abSDave Airlie } 13584ce001abSDave Airlie if (radeon_connector->devices & ATOM_DEVICE_TV1_SUPPORT) { 1359771fe6b9SJerome Glisse if (bios_0_scratch & (ATOM_S0_TV1_COMPOSITE | ATOM_S0_TV1_COMPOSITE_A)) 1360771fe6b9SJerome Glisse return connector_status_connected; /* CTV */ 1361771fe6b9SJerome Glisse else if (bios_0_scratch & (ATOM_S0_TV1_SVIDEO | ATOM_S0_TV1_SVIDEO_A)) 1362771fe6b9SJerome Glisse return connector_status_connected; /* STV */ 1363771fe6b9SJerome Glisse } 1364771fe6b9SJerome Glisse return connector_status_disconnected; 1365771fe6b9SJerome Glisse } 1366771fe6b9SJerome Glisse 1367771fe6b9SJerome Glisse static void radeon_atom_encoder_prepare(struct drm_encoder *encoder) 1368771fe6b9SJerome Glisse { 1369771fe6b9SJerome Glisse radeon_atom_output_lock(encoder, true); 1370771fe6b9SJerome Glisse radeon_atom_encoder_dpms(encoder, DRM_MODE_DPMS_OFF); 1371771fe6b9SJerome Glisse } 1372771fe6b9SJerome Glisse 1373771fe6b9SJerome Glisse static void radeon_atom_encoder_commit(struct drm_encoder *encoder) 1374771fe6b9SJerome Glisse { 1375771fe6b9SJerome Glisse radeon_atom_encoder_dpms(encoder, DRM_MODE_DPMS_ON); 1376771fe6b9SJerome Glisse radeon_atom_output_lock(encoder, false); 1377771fe6b9SJerome Glisse } 1378771fe6b9SJerome Glisse 13794ce001abSDave Airlie static void radeon_atom_encoder_disable(struct drm_encoder *encoder) 13804ce001abSDave Airlie { 13814ce001abSDave Airlie struct radeon_encoder *radeon_encoder = to_radeon_encoder(encoder); 13824ce001abSDave Airlie radeon_atom_encoder_dpms(encoder, DRM_MODE_DPMS_OFF); 13834ce001abSDave Airlie radeon_encoder->active_device = 0; 13844ce001abSDave Airlie } 13854ce001abSDave Airlie 1386771fe6b9SJerome Glisse static const struct drm_encoder_helper_funcs radeon_atom_dig_helper_funcs = { 1387771fe6b9SJerome Glisse .dpms = radeon_atom_encoder_dpms, 1388771fe6b9SJerome Glisse .mode_fixup = radeon_atom_mode_fixup, 1389771fe6b9SJerome Glisse .prepare = radeon_atom_encoder_prepare, 1390771fe6b9SJerome Glisse .mode_set = radeon_atom_encoder_mode_set, 1391771fe6b9SJerome Glisse .commit = radeon_atom_encoder_commit, 13924ce001abSDave Airlie .disable = radeon_atom_encoder_disable, 1393771fe6b9SJerome Glisse /* no detect for TMDS/LVDS yet */ 1394771fe6b9SJerome Glisse }; 1395771fe6b9SJerome Glisse 1396771fe6b9SJerome Glisse static const struct drm_encoder_helper_funcs radeon_atom_dac_helper_funcs = { 1397771fe6b9SJerome Glisse .dpms = radeon_atom_encoder_dpms, 1398771fe6b9SJerome Glisse .mode_fixup = radeon_atom_mode_fixup, 1399771fe6b9SJerome Glisse .prepare = radeon_atom_encoder_prepare, 1400771fe6b9SJerome Glisse .mode_set = radeon_atom_encoder_mode_set, 1401771fe6b9SJerome Glisse .commit = radeon_atom_encoder_commit, 1402771fe6b9SJerome Glisse .detect = radeon_atom_dac_detect, 1403771fe6b9SJerome Glisse }; 1404771fe6b9SJerome Glisse 1405771fe6b9SJerome Glisse void radeon_enc_destroy(struct drm_encoder *encoder) 1406771fe6b9SJerome Glisse { 1407771fe6b9SJerome Glisse struct radeon_encoder *radeon_encoder = to_radeon_encoder(encoder); 1408771fe6b9SJerome Glisse kfree(radeon_encoder->enc_priv); 1409771fe6b9SJerome Glisse drm_encoder_cleanup(encoder); 1410771fe6b9SJerome Glisse kfree(radeon_encoder); 1411771fe6b9SJerome Glisse } 1412771fe6b9SJerome Glisse 1413771fe6b9SJerome Glisse static const struct drm_encoder_funcs radeon_atom_enc_funcs = { 1414771fe6b9SJerome Glisse .destroy = radeon_enc_destroy, 1415771fe6b9SJerome Glisse }; 1416771fe6b9SJerome Glisse 14174ce001abSDave Airlie struct radeon_encoder_atom_dac * 14184ce001abSDave Airlie radeon_atombios_set_dac_info(struct radeon_encoder *radeon_encoder) 14194ce001abSDave Airlie { 14204ce001abSDave Airlie struct radeon_encoder_atom_dac *dac = kzalloc(sizeof(struct radeon_encoder_atom_dac), GFP_KERNEL); 14214ce001abSDave Airlie 14224ce001abSDave Airlie if (!dac) 14234ce001abSDave Airlie return NULL; 14244ce001abSDave Airlie 14254ce001abSDave Airlie dac->tv_std = TV_STD_NTSC; 14264ce001abSDave Airlie return dac; 14274ce001abSDave Airlie } 14284ce001abSDave Airlie 1429771fe6b9SJerome Glisse struct radeon_encoder_atom_dig * 1430771fe6b9SJerome Glisse radeon_atombios_set_dig_info(struct radeon_encoder *radeon_encoder) 1431771fe6b9SJerome Glisse { 1432771fe6b9SJerome Glisse struct radeon_encoder_atom_dig *dig = kzalloc(sizeof(struct radeon_encoder_atom_dig), GFP_KERNEL); 1433771fe6b9SJerome Glisse 1434771fe6b9SJerome Glisse if (!dig) 1435771fe6b9SJerome Glisse return NULL; 1436771fe6b9SJerome Glisse 1437771fe6b9SJerome Glisse /* coherent mode by default */ 1438771fe6b9SJerome Glisse dig->coherent_mode = true; 1439771fe6b9SJerome Glisse 1440771fe6b9SJerome Glisse return dig; 1441771fe6b9SJerome Glisse } 1442771fe6b9SJerome Glisse 1443771fe6b9SJerome Glisse void 1444771fe6b9SJerome Glisse radeon_add_atom_encoder(struct drm_device *dev, uint32_t encoder_id, uint32_t supported_device) 1445771fe6b9SJerome Glisse { 1446dfee5614SDave Airlie struct radeon_device *rdev = dev->dev_private; 1447771fe6b9SJerome Glisse struct drm_encoder *encoder; 1448771fe6b9SJerome Glisse struct radeon_encoder *radeon_encoder; 1449771fe6b9SJerome Glisse 1450771fe6b9SJerome Glisse /* see if we already added it */ 1451771fe6b9SJerome Glisse list_for_each_entry(encoder, &dev->mode_config.encoder_list, head) { 1452771fe6b9SJerome Glisse radeon_encoder = to_radeon_encoder(encoder); 1453771fe6b9SJerome Glisse if (radeon_encoder->encoder_id == encoder_id) { 1454771fe6b9SJerome Glisse radeon_encoder->devices |= supported_device; 1455771fe6b9SJerome Glisse return; 1456771fe6b9SJerome Glisse } 1457771fe6b9SJerome Glisse 1458771fe6b9SJerome Glisse } 1459771fe6b9SJerome Glisse 1460771fe6b9SJerome Glisse /* add a new one */ 1461771fe6b9SJerome Glisse radeon_encoder = kzalloc(sizeof(struct radeon_encoder), GFP_KERNEL); 1462771fe6b9SJerome Glisse if (!radeon_encoder) 1463771fe6b9SJerome Glisse return; 1464771fe6b9SJerome Glisse 1465771fe6b9SJerome Glisse encoder = &radeon_encoder->base; 1466dfee5614SDave Airlie if (rdev->flags & RADEON_SINGLE_CRTC) 1467dfee5614SDave Airlie encoder->possible_crtcs = 0x1; 1468dfee5614SDave Airlie else 1469771fe6b9SJerome Glisse encoder->possible_crtcs = 0x3; 1470771fe6b9SJerome Glisse 1471771fe6b9SJerome Glisse radeon_encoder->enc_priv = NULL; 1472771fe6b9SJerome Glisse 1473771fe6b9SJerome Glisse radeon_encoder->encoder_id = encoder_id; 1474771fe6b9SJerome Glisse radeon_encoder->devices = supported_device; 1475c93bb85bSJerome Glisse radeon_encoder->rmx_type = RMX_OFF; 1476771fe6b9SJerome Glisse 1477771fe6b9SJerome Glisse switch (radeon_encoder->encoder_id) { 1478771fe6b9SJerome Glisse case ENCODER_OBJECT_ID_INTERNAL_LVDS: 1479771fe6b9SJerome Glisse case ENCODER_OBJECT_ID_INTERNAL_TMDS1: 1480771fe6b9SJerome Glisse case ENCODER_OBJECT_ID_INTERNAL_KLDSCP_TMDS1: 1481771fe6b9SJerome Glisse case ENCODER_OBJECT_ID_INTERNAL_LVTM1: 1482771fe6b9SJerome Glisse if (radeon_encoder->devices & (ATOM_DEVICE_LCD_SUPPORT)) { 1483771fe6b9SJerome Glisse radeon_encoder->rmx_type = RMX_FULL; 1484771fe6b9SJerome Glisse drm_encoder_init(dev, encoder, &radeon_atom_enc_funcs, DRM_MODE_ENCODER_LVDS); 1485771fe6b9SJerome Glisse radeon_encoder->enc_priv = radeon_atombios_get_lvds_info(radeon_encoder); 1486771fe6b9SJerome Glisse } else { 1487771fe6b9SJerome Glisse drm_encoder_init(dev, encoder, &radeon_atom_enc_funcs, DRM_MODE_ENCODER_TMDS); 1488771fe6b9SJerome Glisse radeon_encoder->enc_priv = radeon_atombios_set_dig_info(radeon_encoder); 1489771fe6b9SJerome Glisse } 1490771fe6b9SJerome Glisse drm_encoder_helper_add(encoder, &radeon_atom_dig_helper_funcs); 1491771fe6b9SJerome Glisse break; 1492771fe6b9SJerome Glisse case ENCODER_OBJECT_ID_INTERNAL_DAC1: 1493771fe6b9SJerome Glisse drm_encoder_init(dev, encoder, &radeon_atom_enc_funcs, DRM_MODE_ENCODER_DAC); 1494771fe6b9SJerome Glisse drm_encoder_helper_add(encoder, &radeon_atom_dac_helper_funcs); 1495771fe6b9SJerome Glisse break; 1496771fe6b9SJerome Glisse case ENCODER_OBJECT_ID_INTERNAL_DAC2: 1497771fe6b9SJerome Glisse case ENCODER_OBJECT_ID_INTERNAL_KLDSCP_DAC1: 1498771fe6b9SJerome Glisse case ENCODER_OBJECT_ID_INTERNAL_KLDSCP_DAC2: 1499771fe6b9SJerome Glisse drm_encoder_init(dev, encoder, &radeon_atom_enc_funcs, DRM_MODE_ENCODER_TVDAC); 15004ce001abSDave Airlie radeon_encoder->enc_priv = radeon_atombios_set_dac_info(radeon_encoder); 1501771fe6b9SJerome Glisse drm_encoder_helper_add(encoder, &radeon_atom_dac_helper_funcs); 1502771fe6b9SJerome Glisse break; 1503771fe6b9SJerome Glisse case ENCODER_OBJECT_ID_INTERNAL_DVO1: 1504771fe6b9SJerome Glisse case ENCODER_OBJECT_ID_INTERNAL_KLDSCP_DVO1: 1505771fe6b9SJerome Glisse case ENCODER_OBJECT_ID_INTERNAL_DDI: 1506771fe6b9SJerome Glisse case ENCODER_OBJECT_ID_INTERNAL_UNIPHY: 1507771fe6b9SJerome Glisse case ENCODER_OBJECT_ID_INTERNAL_KLDSCP_LVTMA: 1508771fe6b9SJerome Glisse case ENCODER_OBJECT_ID_INTERNAL_UNIPHY1: 1509771fe6b9SJerome Glisse case ENCODER_OBJECT_ID_INTERNAL_UNIPHY2: 151060d15f55SAlex Deucher if (radeon_encoder->devices & (ATOM_DEVICE_LCD_SUPPORT)) { 151160d15f55SAlex Deucher radeon_encoder->rmx_type = RMX_FULL; 151260d15f55SAlex Deucher drm_encoder_init(dev, encoder, &radeon_atom_enc_funcs, DRM_MODE_ENCODER_LVDS); 151360d15f55SAlex Deucher radeon_encoder->enc_priv = radeon_atombios_get_lvds_info(radeon_encoder); 151460d15f55SAlex Deucher } else { 1515771fe6b9SJerome Glisse drm_encoder_init(dev, encoder, &radeon_atom_enc_funcs, DRM_MODE_ENCODER_TMDS); 1516771fe6b9SJerome Glisse radeon_encoder->enc_priv = radeon_atombios_set_dig_info(radeon_encoder); 151760d15f55SAlex Deucher } 1518771fe6b9SJerome Glisse drm_encoder_helper_add(encoder, &radeon_atom_dig_helper_funcs); 1519771fe6b9SJerome Glisse break; 1520771fe6b9SJerome Glisse } 1521dafc3bd5SChristian Koenig 1522dafc3bd5SChristian Koenig r600_hdmi_init(encoder); 1523771fe6b9SJerome Glisse } 1524