1254885Sdumbbell/* 2254885Sdumbbell * Copyright 2007-11 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 "radeon_asic.h" /* Declares several prototypes; clang is pleased. */ 35254885Sdumbbell#include "atom.h" 36254885Sdumbbell 37254885Sdumbbellstatic u8 38254885Sdumbbellradeon_atom_get_backlight_level_from_reg(struct radeon_device *rdev) 39254885Sdumbbell{ 40254885Sdumbbell u8 backlight_level; 41254885Sdumbbell u32 bios_2_scratch; 42254885Sdumbbell 43254885Sdumbbell if (rdev->family >= CHIP_R600) 44254885Sdumbbell bios_2_scratch = RREG32(R600_BIOS_2_SCRATCH); 45254885Sdumbbell else 46254885Sdumbbell bios_2_scratch = RREG32(RADEON_BIOS_2_SCRATCH); 47254885Sdumbbell 48254885Sdumbbell backlight_level = ((bios_2_scratch & ATOM_S2_CURRENT_BL_LEVEL_MASK) >> 49254885Sdumbbell ATOM_S2_CURRENT_BL_LEVEL_SHIFT); 50254885Sdumbbell 51254885Sdumbbell return backlight_level; 52254885Sdumbbell} 53254885Sdumbbell 54254885Sdumbbellstatic void 55254885Sdumbbellradeon_atom_set_backlight_level_to_reg(struct radeon_device *rdev, 56254885Sdumbbell u8 backlight_level) 57254885Sdumbbell{ 58254885Sdumbbell u32 bios_2_scratch; 59254885Sdumbbell 60254885Sdumbbell if (rdev->family >= CHIP_R600) 61254885Sdumbbell bios_2_scratch = RREG32(R600_BIOS_2_SCRATCH); 62254885Sdumbbell else 63254885Sdumbbell bios_2_scratch = RREG32(RADEON_BIOS_2_SCRATCH); 64254885Sdumbbell 65254885Sdumbbell bios_2_scratch &= ~ATOM_S2_CURRENT_BL_LEVEL_MASK; 66254885Sdumbbell bios_2_scratch |= ((backlight_level << ATOM_S2_CURRENT_BL_LEVEL_SHIFT) & 67254885Sdumbbell ATOM_S2_CURRENT_BL_LEVEL_MASK); 68254885Sdumbbell 69254885Sdumbbell if (rdev->family >= CHIP_R600) 70254885Sdumbbell WREG32(R600_BIOS_2_SCRATCH, bios_2_scratch); 71254885Sdumbbell else 72254885Sdumbbell WREG32(RADEON_BIOS_2_SCRATCH, bios_2_scratch); 73254885Sdumbbell} 74254885Sdumbbell 75254885Sdumbbellu8 76254885Sdumbbellatombios_get_backlight_level(struct radeon_encoder *radeon_encoder) 77254885Sdumbbell{ 78254885Sdumbbell struct drm_device *dev = radeon_encoder->base.dev; 79254885Sdumbbell struct radeon_device *rdev = dev->dev_private; 80254885Sdumbbell 81254885Sdumbbell if (!(rdev->mode_info.firmware_flags & ATOM_BIOS_INFO_BL_CONTROLLED_BY_GPU)) 82254885Sdumbbell return 0; 83254885Sdumbbell 84254885Sdumbbell return radeon_atom_get_backlight_level_from_reg(rdev); 85254885Sdumbbell} 86254885Sdumbbell 87254885Sdumbbellvoid 88254885Sdumbbellatombios_set_backlight_level(struct radeon_encoder *radeon_encoder, u8 level) 89254885Sdumbbell{ 90254885Sdumbbell struct drm_encoder *encoder = &radeon_encoder->base; 91254885Sdumbbell struct drm_device *dev = radeon_encoder->base.dev; 92254885Sdumbbell struct radeon_device *rdev = dev->dev_private; 93254885Sdumbbell struct radeon_encoder_atom_dig *dig; 94254885Sdumbbell DISPLAY_DEVICE_OUTPUT_CONTROL_PS_ALLOCATION args; 95254885Sdumbbell int index; 96254885Sdumbbell 97254885Sdumbbell if (!(rdev->mode_info.firmware_flags & ATOM_BIOS_INFO_BL_CONTROLLED_BY_GPU)) 98254885Sdumbbell return; 99254885Sdumbbell 100254885Sdumbbell if ((radeon_encoder->devices & (ATOM_DEVICE_LCD_SUPPORT)) && 101254885Sdumbbell radeon_encoder->enc_priv) { 102254885Sdumbbell dig = radeon_encoder->enc_priv; 103254885Sdumbbell dig->backlight_level = level; 104254885Sdumbbell radeon_atom_set_backlight_level_to_reg(rdev, dig->backlight_level); 105254885Sdumbbell 106254885Sdumbbell switch (radeon_encoder->encoder_id) { 107254885Sdumbbell case ENCODER_OBJECT_ID_INTERNAL_LVDS: 108254885Sdumbbell case ENCODER_OBJECT_ID_INTERNAL_LVTM1: 109254885Sdumbbell index = GetIndexIntoMasterTable(COMMAND, LCD1OutputControl); 110254885Sdumbbell if (dig->backlight_level == 0) { 111254885Sdumbbell args.ucAction = ATOM_LCD_BLOFF; 112254885Sdumbbell atom_execute_table(rdev->mode_info.atom_context, index, (uint32_t *)&args); 113254885Sdumbbell } else { 114254885Sdumbbell args.ucAction = ATOM_LCD_BL_BRIGHTNESS_CONTROL; 115254885Sdumbbell atom_execute_table(rdev->mode_info.atom_context, index, (uint32_t *)&args); 116254885Sdumbbell args.ucAction = ATOM_LCD_BLON; 117254885Sdumbbell atom_execute_table(rdev->mode_info.atom_context, index, (uint32_t *)&args); 118254885Sdumbbell } 119254885Sdumbbell break; 120254885Sdumbbell case ENCODER_OBJECT_ID_INTERNAL_UNIPHY: 121254885Sdumbbell case ENCODER_OBJECT_ID_INTERNAL_KLDSCP_LVTMA: 122254885Sdumbbell case ENCODER_OBJECT_ID_INTERNAL_UNIPHY1: 123254885Sdumbbell case ENCODER_OBJECT_ID_INTERNAL_UNIPHY2: 124254885Sdumbbell if (dig->backlight_level == 0) 125254885Sdumbbell atombios_dig_transmitter_setup(encoder, ATOM_TRANSMITTER_ACTION_LCD_BLOFF, 0, 0); 126254885Sdumbbell else { 127254885Sdumbbell atombios_dig_transmitter_setup(encoder, ATOM_TRANSMITTER_ACTION_BL_BRIGHTNESS_CONTROL, 0, 0); 128254885Sdumbbell atombios_dig_transmitter_setup(encoder, ATOM_TRANSMITTER_ACTION_LCD_BLON, 0, 0); 129254885Sdumbbell } 130254885Sdumbbell break; 131254885Sdumbbell default: 132254885Sdumbbell break; 133254885Sdumbbell } 134254885Sdumbbell } 135254885Sdumbbell} 136254885Sdumbbell 137254885Sdumbbell#if defined(CONFIG_BACKLIGHT_CLASS_DEVICE) || defined(CONFIG_BACKLIGHT_CLASS_DEVICE_MODULE) 138254885Sdumbbell 139254885Sdumbbellstatic u8 radeon_atom_bl_level(struct backlight_device *bd) 140254885Sdumbbell{ 141254885Sdumbbell u8 level; 142254885Sdumbbell 143254885Sdumbbell /* Convert brightness to hardware level */ 144254885Sdumbbell if (bd->props.brightness < 0) 145254885Sdumbbell level = 0; 146254885Sdumbbell else if (bd->props.brightness > RADEON_MAX_BL_LEVEL) 147254885Sdumbbell level = RADEON_MAX_BL_LEVEL; 148254885Sdumbbell else 149254885Sdumbbell level = bd->props.brightness; 150254885Sdumbbell 151254885Sdumbbell return level; 152254885Sdumbbell} 153254885Sdumbbell 154254885Sdumbbellstatic int radeon_atom_backlight_update_status(struct backlight_device *bd) 155254885Sdumbbell{ 156254885Sdumbbell struct radeon_backlight_privdata *pdata = bl_get_data(bd); 157254885Sdumbbell struct radeon_encoder *radeon_encoder = pdata->encoder; 158254885Sdumbbell 159254885Sdumbbell atombios_set_backlight_level(radeon_encoder, radeon_atom_bl_level(bd)); 160254885Sdumbbell 161254885Sdumbbell return 0; 162254885Sdumbbell} 163254885Sdumbbell 164254885Sdumbbellstatic int radeon_atom_backlight_get_brightness(struct backlight_device *bd) 165254885Sdumbbell{ 166254885Sdumbbell struct radeon_backlight_privdata *pdata = bl_get_data(bd); 167254885Sdumbbell struct radeon_encoder *radeon_encoder = pdata->encoder; 168254885Sdumbbell struct drm_device *dev = radeon_encoder->base.dev; 169254885Sdumbbell struct radeon_device *rdev = dev->dev_private; 170254885Sdumbbell 171254885Sdumbbell return radeon_atom_get_backlight_level_from_reg(rdev); 172254885Sdumbbell} 173254885Sdumbbell 174254885Sdumbbellstatic const struct backlight_ops radeon_atom_backlight_ops = { 175254885Sdumbbell .get_brightness = radeon_atom_backlight_get_brightness, 176254885Sdumbbell .update_status = radeon_atom_backlight_update_status, 177254885Sdumbbell}; 178254885Sdumbbell 179254885Sdumbbellvoid radeon_atom_backlight_init(struct radeon_encoder *radeon_encoder, 180254885Sdumbbell struct drm_connector *drm_connector) 181254885Sdumbbell{ 182254885Sdumbbell struct drm_device *dev = radeon_encoder->base.dev; 183254885Sdumbbell struct radeon_device *rdev = dev->dev_private; 184254885Sdumbbell struct backlight_device *bd; 185254885Sdumbbell struct backlight_properties props; 186254885Sdumbbell struct radeon_backlight_privdata *pdata; 187254885Sdumbbell struct radeon_encoder_atom_dig *dig; 188254885Sdumbbell u8 backlight_level; 189254885Sdumbbell char bl_name[16]; 190254885Sdumbbell 191254885Sdumbbell if (!radeon_encoder->enc_priv) 192254885Sdumbbell return; 193254885Sdumbbell 194254885Sdumbbell if (!rdev->is_atom_bios) 195254885Sdumbbell return; 196254885Sdumbbell 197254885Sdumbbell if (!(rdev->mode_info.firmware_flags & ATOM_BIOS_INFO_BL_CONTROLLED_BY_GPU)) 198254885Sdumbbell return; 199254885Sdumbbell 200280183Sdumbbell pdata = malloc(sizeof(struct radeon_backlight_privdata), DRM_MEM_DRIVER, M_NOWAIT); 201254885Sdumbbell if (!pdata) { 202254885Sdumbbell DRM_ERROR("Memory allocation failed\n"); 203254885Sdumbbell goto error; 204254885Sdumbbell } 205254885Sdumbbell 206254885Sdumbbell memset(&props, 0, sizeof(props)); 207254885Sdumbbell props.max_brightness = RADEON_MAX_BL_LEVEL; 208254885Sdumbbell props.type = BACKLIGHT_RAW; 209254885Sdumbbell snprintf(bl_name, sizeof(bl_name), 210254885Sdumbbell "radeon_bl%d", dev->primary->index); 211254885Sdumbbell bd = backlight_device_register(bl_name, &drm_connector->kdev, 212254885Sdumbbell pdata, &radeon_atom_backlight_ops, &props); 213254885Sdumbbell if (IS_ERR(bd)) { 214254885Sdumbbell DRM_ERROR("Backlight registration failed\n"); 215254885Sdumbbell goto error; 216254885Sdumbbell } 217254885Sdumbbell 218254885Sdumbbell pdata->encoder = radeon_encoder; 219254885Sdumbbell 220254885Sdumbbell backlight_level = radeon_atom_get_backlight_level_from_reg(rdev); 221254885Sdumbbell 222254885Sdumbbell dig = radeon_encoder->enc_priv; 223254885Sdumbbell dig->bl_dev = bd; 224254885Sdumbbell 225254885Sdumbbell bd->props.brightness = radeon_atom_backlight_get_brightness(bd); 226254885Sdumbbell bd->props.power = FB_BLANK_UNBLANK; 227254885Sdumbbell backlight_update_status(bd); 228254885Sdumbbell 229254885Sdumbbell DRM_INFO("radeon atom DIG backlight initialized\n"); 230254885Sdumbbell 231254885Sdumbbell return; 232254885Sdumbbell 233254885Sdumbbellerror: 234254885Sdumbbell free(pdata, DRM_MEM_DRIVER); 235254885Sdumbbell return; 236254885Sdumbbell} 237254885Sdumbbell 238254885Sdumbbellstatic void radeon_atom_backlight_exit(struct radeon_encoder *radeon_encoder) 239254885Sdumbbell{ 240254885Sdumbbell struct drm_device *dev = radeon_encoder->base.dev; 241254885Sdumbbell struct radeon_device *rdev = dev->dev_private; 242254885Sdumbbell struct backlight_device *bd = NULL; 243254885Sdumbbell struct radeon_encoder_atom_dig *dig; 244254885Sdumbbell 245254885Sdumbbell if (!radeon_encoder->enc_priv) 246254885Sdumbbell return; 247254885Sdumbbell 248254885Sdumbbell if (!rdev->is_atom_bios) 249254885Sdumbbell return; 250254885Sdumbbell 251254885Sdumbbell if (!(rdev->mode_info.firmware_flags & ATOM_BIOS_INFO_BL_CONTROLLED_BY_GPU)) 252254885Sdumbbell return; 253254885Sdumbbell 254254885Sdumbbell dig = radeon_encoder->enc_priv; 255254885Sdumbbell bd = dig->bl_dev; 256254885Sdumbbell dig->bl_dev = NULL; 257254885Sdumbbell 258254885Sdumbbell if (bd) { 259254885Sdumbbell struct radeon_legacy_backlight_privdata *pdata; 260254885Sdumbbell 261254885Sdumbbell pdata = bl_get_data(bd); 262254885Sdumbbell backlight_device_unregister(bd); 263254885Sdumbbell free(pdata, DRM_MEM_DRIVER); 264254885Sdumbbell 265254885Sdumbbell DRM_INFO("radeon atom LVDS backlight unloaded\n"); 266254885Sdumbbell } 267254885Sdumbbell} 268254885Sdumbbell 269254885Sdumbbell#else /* !CONFIG_BACKLIGHT_CLASS_DEVICE */ 270254885Sdumbbell 271254885Sdumbbellvoid radeon_atom_backlight_init(struct radeon_encoder *radeon_encoder, 272254885Sdumbbell struct drm_connector *drm_connector) 273254885Sdumbbell{ 274254885Sdumbbell} 275254885Sdumbbell 276254885Sdumbbellstatic void radeon_atom_backlight_exit(struct radeon_encoder *encoder) 277254885Sdumbbell{ 278254885Sdumbbell} 279254885Sdumbbell 280254885Sdumbbell#endif 281254885Sdumbbell 282280183Sdumbbell#ifdef FREEBSD_WIP /* FreeBSD: to please GCC 4.2. */ 283280183Sdumbbell/* evil but including atombios.h is much worse */ 284280183Sdumbbellbool radeon_atom_get_tv_timings(struct radeon_device *rdev, int index, 285280183Sdumbbell struct drm_display_mode *mode); 286280183Sdumbbell#endif 287254885Sdumbbell 288280183Sdumbbell 289254885Sdumbbellstatic inline bool radeon_encoder_is_digital(struct drm_encoder *encoder) 290254885Sdumbbell{ 291254885Sdumbbell struct radeon_encoder *radeon_encoder = to_radeon_encoder(encoder); 292254885Sdumbbell switch (radeon_encoder->encoder_id) { 293254885Sdumbbell case ENCODER_OBJECT_ID_INTERNAL_LVDS: 294254885Sdumbbell case ENCODER_OBJECT_ID_INTERNAL_TMDS1: 295254885Sdumbbell case ENCODER_OBJECT_ID_INTERNAL_KLDSCP_TMDS1: 296254885Sdumbbell case ENCODER_OBJECT_ID_INTERNAL_LVTM1: 297254885Sdumbbell case ENCODER_OBJECT_ID_INTERNAL_DVO1: 298254885Sdumbbell case ENCODER_OBJECT_ID_INTERNAL_KLDSCP_DVO1: 299254885Sdumbbell case ENCODER_OBJECT_ID_INTERNAL_DDI: 300254885Sdumbbell case ENCODER_OBJECT_ID_INTERNAL_UNIPHY: 301254885Sdumbbell case ENCODER_OBJECT_ID_INTERNAL_KLDSCP_LVTMA: 302254885Sdumbbell case ENCODER_OBJECT_ID_INTERNAL_UNIPHY1: 303254885Sdumbbell case ENCODER_OBJECT_ID_INTERNAL_UNIPHY2: 304254885Sdumbbell return true; 305254885Sdumbbell default: 306254885Sdumbbell return false; 307254885Sdumbbell } 308254885Sdumbbell} 309254885Sdumbbell 310254885Sdumbbellstatic bool radeon_atom_mode_fixup(struct drm_encoder *encoder, 311280183Sdumbbell const struct drm_display_mode *mode, 312254885Sdumbbell struct drm_display_mode *adjusted_mode) 313254885Sdumbbell{ 314254885Sdumbbell struct radeon_encoder *radeon_encoder = to_radeon_encoder(encoder); 315254885Sdumbbell struct drm_device *dev = encoder->dev; 316254885Sdumbbell struct radeon_device *rdev = dev->dev_private; 317254885Sdumbbell 318254885Sdumbbell /* set the active encoder to connector routing */ 319254885Sdumbbell radeon_encoder_set_active_device(encoder); 320254885Sdumbbell drm_mode_set_crtcinfo(adjusted_mode, 0); 321254885Sdumbbell 322254885Sdumbbell /* hw bug */ 323254885Sdumbbell if ((mode->flags & DRM_MODE_FLAG_INTERLACE) 324254885Sdumbbell && (mode->crtc_vsync_start < (mode->crtc_vdisplay + 2))) 325254885Sdumbbell adjusted_mode->crtc_vsync_start = adjusted_mode->crtc_vdisplay + 2; 326254885Sdumbbell 327254885Sdumbbell /* get the native mode for LVDS */ 328254885Sdumbbell if (radeon_encoder->active_device & (ATOM_DEVICE_LCD_SUPPORT)) 329254885Sdumbbell radeon_panel_mode_fixup(encoder, adjusted_mode); 330254885Sdumbbell 331254885Sdumbbell /* get the native mode for TV */ 332254885Sdumbbell if (radeon_encoder->active_device & (ATOM_DEVICE_TV_SUPPORT)) { 333254885Sdumbbell struct radeon_encoder_atom_dac *tv_dac = radeon_encoder->enc_priv; 334254885Sdumbbell if (tv_dac) { 335254885Sdumbbell if (tv_dac->tv_std == TV_STD_NTSC || 336254885Sdumbbell tv_dac->tv_std == TV_STD_NTSC_J || 337254885Sdumbbell tv_dac->tv_std == TV_STD_PAL_M) 338254885Sdumbbell radeon_atom_get_tv_timings(rdev, 0, adjusted_mode); 339254885Sdumbbell else 340254885Sdumbbell radeon_atom_get_tv_timings(rdev, 1, adjusted_mode); 341254885Sdumbbell } 342254885Sdumbbell } 343254885Sdumbbell 344254885Sdumbbell if (ASIC_IS_DCE3(rdev) && 345254885Sdumbbell ((radeon_encoder->active_device & (ATOM_DEVICE_DFP_SUPPORT | ATOM_DEVICE_LCD_SUPPORT)) || 346254885Sdumbbell (radeon_encoder_get_dp_bridge_encoder_id(encoder) != ENCODER_OBJECT_ID_NONE))) { 347254885Sdumbbell struct drm_connector *connector = radeon_get_connector_for_encoder(encoder); 348254885Sdumbbell radeon_dp_set_link_config(connector, adjusted_mode); 349254885Sdumbbell } 350254885Sdumbbell 351254885Sdumbbell return true; 352254885Sdumbbell} 353254885Sdumbbell 354254885Sdumbbellstatic void 355254885Sdumbbellatombios_dac_setup(struct drm_encoder *encoder, int action) 356254885Sdumbbell{ 357254885Sdumbbell struct drm_device *dev = encoder->dev; 358254885Sdumbbell struct radeon_device *rdev = dev->dev_private; 359254885Sdumbbell struct radeon_encoder *radeon_encoder = to_radeon_encoder(encoder); 360254885Sdumbbell DAC_ENCODER_CONTROL_PS_ALLOCATION args; 361254885Sdumbbell int index = 0; 362254885Sdumbbell struct radeon_encoder_atom_dac *dac_info = radeon_encoder->enc_priv; 363254885Sdumbbell 364254885Sdumbbell memset(&args, 0, sizeof(args)); 365254885Sdumbbell 366254885Sdumbbell switch (radeon_encoder->encoder_id) { 367254885Sdumbbell case ENCODER_OBJECT_ID_INTERNAL_DAC1: 368254885Sdumbbell case ENCODER_OBJECT_ID_INTERNAL_KLDSCP_DAC1: 369254885Sdumbbell index = GetIndexIntoMasterTable(COMMAND, DAC1EncoderControl); 370254885Sdumbbell break; 371254885Sdumbbell case ENCODER_OBJECT_ID_INTERNAL_DAC2: 372254885Sdumbbell case ENCODER_OBJECT_ID_INTERNAL_KLDSCP_DAC2: 373254885Sdumbbell index = GetIndexIntoMasterTable(COMMAND, DAC2EncoderControl); 374254885Sdumbbell break; 375254885Sdumbbell } 376254885Sdumbbell 377254885Sdumbbell args.ucAction = action; 378254885Sdumbbell 379254885Sdumbbell if (radeon_encoder->active_device & (ATOM_DEVICE_CRT_SUPPORT)) 380254885Sdumbbell args.ucDacStandard = ATOM_DAC1_PS2; 381254885Sdumbbell else if (radeon_encoder->active_device & (ATOM_DEVICE_CV_SUPPORT)) 382254885Sdumbbell args.ucDacStandard = ATOM_DAC1_CV; 383254885Sdumbbell else { 384254885Sdumbbell switch (dac_info->tv_std) { 385254885Sdumbbell case TV_STD_PAL: 386254885Sdumbbell case TV_STD_PAL_M: 387254885Sdumbbell case TV_STD_SCART_PAL: 388254885Sdumbbell case TV_STD_SECAM: 389254885Sdumbbell case TV_STD_PAL_CN: 390254885Sdumbbell args.ucDacStandard = ATOM_DAC1_PAL; 391254885Sdumbbell break; 392254885Sdumbbell case TV_STD_NTSC: 393254885Sdumbbell case TV_STD_NTSC_J: 394254885Sdumbbell case TV_STD_PAL_60: 395254885Sdumbbell default: 396254885Sdumbbell args.ucDacStandard = ATOM_DAC1_NTSC; 397254885Sdumbbell break; 398254885Sdumbbell } 399254885Sdumbbell } 400254885Sdumbbell args.usPixelClock = cpu_to_le16(radeon_encoder->pixel_clock / 10); 401254885Sdumbbell 402254885Sdumbbell atom_execute_table(rdev->mode_info.atom_context, index, (uint32_t *)&args); 403254885Sdumbbell 404254885Sdumbbell} 405254885Sdumbbell 406254885Sdumbbellstatic void 407254885Sdumbbellatombios_tv_setup(struct drm_encoder *encoder, int action) 408254885Sdumbbell{ 409254885Sdumbbell struct drm_device *dev = encoder->dev; 410254885Sdumbbell struct radeon_device *rdev = dev->dev_private; 411254885Sdumbbell struct radeon_encoder *radeon_encoder = to_radeon_encoder(encoder); 412254885Sdumbbell TV_ENCODER_CONTROL_PS_ALLOCATION args; 413254885Sdumbbell int index = 0; 414254885Sdumbbell struct radeon_encoder_atom_dac *dac_info = radeon_encoder->enc_priv; 415254885Sdumbbell 416254885Sdumbbell memset(&args, 0, sizeof(args)); 417254885Sdumbbell 418254885Sdumbbell index = GetIndexIntoMasterTable(COMMAND, TVEncoderControl); 419254885Sdumbbell 420254885Sdumbbell args.sTVEncoder.ucAction = action; 421254885Sdumbbell 422254885Sdumbbell if (radeon_encoder->active_device & (ATOM_DEVICE_CV_SUPPORT)) 423254885Sdumbbell args.sTVEncoder.ucTvStandard = ATOM_TV_CV; 424254885Sdumbbell else { 425254885Sdumbbell switch (dac_info->tv_std) { 426254885Sdumbbell case TV_STD_NTSC: 427254885Sdumbbell args.sTVEncoder.ucTvStandard = ATOM_TV_NTSC; 428254885Sdumbbell break; 429254885Sdumbbell case TV_STD_PAL: 430254885Sdumbbell args.sTVEncoder.ucTvStandard = ATOM_TV_PAL; 431254885Sdumbbell break; 432254885Sdumbbell case TV_STD_PAL_M: 433254885Sdumbbell args.sTVEncoder.ucTvStandard = ATOM_TV_PALM; 434254885Sdumbbell break; 435254885Sdumbbell case TV_STD_PAL_60: 436254885Sdumbbell args.sTVEncoder.ucTvStandard = ATOM_TV_PAL60; 437254885Sdumbbell break; 438254885Sdumbbell case TV_STD_NTSC_J: 439254885Sdumbbell args.sTVEncoder.ucTvStandard = ATOM_TV_NTSCJ; 440254885Sdumbbell break; 441254885Sdumbbell case TV_STD_SCART_PAL: 442254885Sdumbbell args.sTVEncoder.ucTvStandard = ATOM_TV_PAL; /* ??? */ 443254885Sdumbbell break; 444254885Sdumbbell case TV_STD_SECAM: 445254885Sdumbbell args.sTVEncoder.ucTvStandard = ATOM_TV_SECAM; 446254885Sdumbbell break; 447254885Sdumbbell case TV_STD_PAL_CN: 448254885Sdumbbell args.sTVEncoder.ucTvStandard = ATOM_TV_PALCN; 449254885Sdumbbell break; 450254885Sdumbbell default: 451254885Sdumbbell args.sTVEncoder.ucTvStandard = ATOM_TV_NTSC; 452254885Sdumbbell break; 453254885Sdumbbell } 454254885Sdumbbell } 455254885Sdumbbell 456254885Sdumbbell args.sTVEncoder.usPixelClock = cpu_to_le16(radeon_encoder->pixel_clock / 10); 457254885Sdumbbell 458254885Sdumbbell atom_execute_table(rdev->mode_info.atom_context, index, (uint32_t *)&args); 459254885Sdumbbell 460254885Sdumbbell} 461254885Sdumbbell 462254885Sdumbbellstatic u8 radeon_atom_get_bpc(struct drm_encoder *encoder) 463254885Sdumbbell{ 464254885Sdumbbell struct drm_connector *connector = radeon_get_connector_for_encoder(encoder); 465254885Sdumbbell int bpc = 8; 466254885Sdumbbell 467254885Sdumbbell if (connector) 468254885Sdumbbell bpc = radeon_get_monitor_bpc(connector); 469254885Sdumbbell 470254885Sdumbbell switch (bpc) { 471254885Sdumbbell case 0: 472254885Sdumbbell return PANEL_BPC_UNDEFINE; 473254885Sdumbbell case 6: 474254885Sdumbbell return PANEL_6BIT_PER_COLOR; 475254885Sdumbbell case 8: 476254885Sdumbbell default: 477254885Sdumbbell return PANEL_8BIT_PER_COLOR; 478254885Sdumbbell case 10: 479254885Sdumbbell return PANEL_10BIT_PER_COLOR; 480254885Sdumbbell case 12: 481254885Sdumbbell return PANEL_12BIT_PER_COLOR; 482254885Sdumbbell case 16: 483254885Sdumbbell return PANEL_16BIT_PER_COLOR; 484254885Sdumbbell } 485254885Sdumbbell} 486254885Sdumbbell 487254885Sdumbbell 488254885Sdumbbellunion dvo_encoder_control { 489254885Sdumbbell ENABLE_EXTERNAL_TMDS_ENCODER_PS_ALLOCATION ext_tmds; 490254885Sdumbbell DVO_ENCODER_CONTROL_PS_ALLOCATION dvo; 491254885Sdumbbell DVO_ENCODER_CONTROL_PS_ALLOCATION_V3 dvo_v3; 492254885Sdumbbell}; 493254885Sdumbbell 494254885Sdumbbellvoid 495254885Sdumbbellatombios_dvo_setup(struct drm_encoder *encoder, int action) 496254885Sdumbbell{ 497254885Sdumbbell struct drm_device *dev = encoder->dev; 498254885Sdumbbell struct radeon_device *rdev = dev->dev_private; 499254885Sdumbbell struct radeon_encoder *radeon_encoder = to_radeon_encoder(encoder); 500254885Sdumbbell union dvo_encoder_control args; 501254885Sdumbbell int index = GetIndexIntoMasterTable(COMMAND, DVOEncoderControl); 502254885Sdumbbell uint8_t frev, crev; 503254885Sdumbbell 504254885Sdumbbell memset(&args, 0, sizeof(args)); 505254885Sdumbbell 506254885Sdumbbell if (!atom_parse_cmd_header(rdev->mode_info.atom_context, index, &frev, &crev)) 507254885Sdumbbell return; 508254885Sdumbbell 509254885Sdumbbell /* some R4xx chips have the wrong frev */ 510254885Sdumbbell if (rdev->family <= CHIP_RV410) 511254885Sdumbbell frev = 1; 512254885Sdumbbell 513254885Sdumbbell switch (frev) { 514254885Sdumbbell case 1: 515254885Sdumbbell switch (crev) { 516254885Sdumbbell case 1: 517254885Sdumbbell /* R4xx, R5xx */ 518254885Sdumbbell args.ext_tmds.sXTmdsEncoder.ucEnable = action; 519254885Sdumbbell 520254885Sdumbbell if (radeon_dig_monitor_is_duallink(encoder, radeon_encoder->pixel_clock)) 521254885Sdumbbell args.ext_tmds.sXTmdsEncoder.ucMisc |= PANEL_ENCODER_MISC_DUAL; 522254885Sdumbbell 523254885Sdumbbell args.ext_tmds.sXTmdsEncoder.ucMisc |= ATOM_PANEL_MISC_888RGB; 524254885Sdumbbell break; 525254885Sdumbbell case 2: 526254885Sdumbbell /* RS600/690/740 */ 527254885Sdumbbell args.dvo.sDVOEncoder.ucAction = action; 528254885Sdumbbell args.dvo.sDVOEncoder.usPixelClock = cpu_to_le16(radeon_encoder->pixel_clock / 10); 529254885Sdumbbell /* DFP1, CRT1, TV1 depending on the type of port */ 530254885Sdumbbell args.dvo.sDVOEncoder.ucDeviceType = ATOM_DEVICE_DFP1_INDEX; 531254885Sdumbbell 532254885Sdumbbell if (radeon_dig_monitor_is_duallink(encoder, radeon_encoder->pixel_clock)) 533254885Sdumbbell args.dvo.sDVOEncoder.usDevAttr.sDigAttrib.ucAttribute |= PANEL_ENCODER_MISC_DUAL; 534254885Sdumbbell break; 535254885Sdumbbell case 3: 536254885Sdumbbell /* R6xx */ 537254885Sdumbbell args.dvo_v3.ucAction = action; 538254885Sdumbbell args.dvo_v3.usPixelClock = cpu_to_le16(radeon_encoder->pixel_clock / 10); 539254885Sdumbbell args.dvo_v3.ucDVOConfig = 0; /* XXX */ 540254885Sdumbbell break; 541254885Sdumbbell default: 542254885Sdumbbell DRM_ERROR("Unknown table version %d, %d\n", frev, crev); 543254885Sdumbbell break; 544254885Sdumbbell } 545254885Sdumbbell break; 546254885Sdumbbell default: 547254885Sdumbbell DRM_ERROR("Unknown table version %d, %d\n", frev, crev); 548254885Sdumbbell break; 549254885Sdumbbell } 550254885Sdumbbell 551254885Sdumbbell atom_execute_table(rdev->mode_info.atom_context, index, (uint32_t *)&args); 552254885Sdumbbell} 553254885Sdumbbell 554254885Sdumbbellunion lvds_encoder_control { 555254885Sdumbbell LVDS_ENCODER_CONTROL_PS_ALLOCATION v1; 556254885Sdumbbell LVDS_ENCODER_CONTROL_PS_ALLOCATION_V2 v2; 557254885Sdumbbell}; 558254885Sdumbbell 559254885Sdumbbellvoid 560254885Sdumbbellatombios_digital_setup(struct drm_encoder *encoder, int action) 561254885Sdumbbell{ 562254885Sdumbbell struct drm_device *dev = encoder->dev; 563254885Sdumbbell struct radeon_device *rdev = dev->dev_private; 564254885Sdumbbell struct radeon_encoder *radeon_encoder = to_radeon_encoder(encoder); 565254885Sdumbbell struct radeon_encoder_atom_dig *dig = radeon_encoder->enc_priv; 566254885Sdumbbell union lvds_encoder_control args; 567254885Sdumbbell int index = 0; 568254885Sdumbbell int hdmi_detected = 0; 569254885Sdumbbell uint8_t frev, crev; 570254885Sdumbbell 571254885Sdumbbell if (!dig) 572254885Sdumbbell return; 573254885Sdumbbell 574254885Sdumbbell if (atombios_get_encoder_mode(encoder) == ATOM_ENCODER_MODE_HDMI) 575254885Sdumbbell hdmi_detected = 1; 576254885Sdumbbell 577254885Sdumbbell memset(&args, 0, sizeof(args)); 578254885Sdumbbell 579254885Sdumbbell switch (radeon_encoder->encoder_id) { 580254885Sdumbbell case ENCODER_OBJECT_ID_INTERNAL_LVDS: 581254885Sdumbbell index = GetIndexIntoMasterTable(COMMAND, LVDSEncoderControl); 582254885Sdumbbell break; 583254885Sdumbbell case ENCODER_OBJECT_ID_INTERNAL_TMDS1: 584254885Sdumbbell case ENCODER_OBJECT_ID_INTERNAL_KLDSCP_TMDS1: 585254885Sdumbbell index = GetIndexIntoMasterTable(COMMAND, TMDS1EncoderControl); 586254885Sdumbbell break; 587254885Sdumbbell case ENCODER_OBJECT_ID_INTERNAL_LVTM1: 588254885Sdumbbell if (radeon_encoder->devices & (ATOM_DEVICE_LCD_SUPPORT)) 589254885Sdumbbell index = GetIndexIntoMasterTable(COMMAND, LVDSEncoderControl); 590254885Sdumbbell else 591254885Sdumbbell index = GetIndexIntoMasterTable(COMMAND, TMDS2EncoderControl); 592254885Sdumbbell break; 593254885Sdumbbell } 594254885Sdumbbell 595254885Sdumbbell if (!atom_parse_cmd_header(rdev->mode_info.atom_context, index, &frev, &crev)) 596254885Sdumbbell return; 597254885Sdumbbell 598254885Sdumbbell switch (frev) { 599254885Sdumbbell case 1: 600254885Sdumbbell case 2: 601254885Sdumbbell switch (crev) { 602254885Sdumbbell case 1: 603254885Sdumbbell args.v1.ucMisc = 0; 604254885Sdumbbell args.v1.ucAction = action; 605254885Sdumbbell if (hdmi_detected) 606254885Sdumbbell args.v1.ucMisc |= PANEL_ENCODER_MISC_HDMI_TYPE; 607254885Sdumbbell args.v1.usPixelClock = cpu_to_le16(radeon_encoder->pixel_clock / 10); 608254885Sdumbbell if (radeon_encoder->devices & (ATOM_DEVICE_LCD_SUPPORT)) { 609254885Sdumbbell if (dig->lcd_misc & ATOM_PANEL_MISC_DUAL) 610254885Sdumbbell args.v1.ucMisc |= PANEL_ENCODER_MISC_DUAL; 611254885Sdumbbell if (dig->lcd_misc & ATOM_PANEL_MISC_888RGB) 612254885Sdumbbell args.v1.ucMisc |= ATOM_PANEL_MISC_888RGB; 613254885Sdumbbell } else { 614254885Sdumbbell if (dig->linkb) 615254885Sdumbbell args.v1.ucMisc |= PANEL_ENCODER_MISC_TMDS_LINKB; 616254885Sdumbbell if (radeon_dig_monitor_is_duallink(encoder, radeon_encoder->pixel_clock)) 617254885Sdumbbell args.v1.ucMisc |= PANEL_ENCODER_MISC_DUAL; 618254885Sdumbbell /*if (pScrn->rgbBits == 8) */ 619254885Sdumbbell args.v1.ucMisc |= ATOM_PANEL_MISC_888RGB; 620254885Sdumbbell } 621254885Sdumbbell break; 622254885Sdumbbell case 2: 623254885Sdumbbell case 3: 624254885Sdumbbell args.v2.ucMisc = 0; 625254885Sdumbbell args.v2.ucAction = action; 626254885Sdumbbell if (crev == 3) { 627254885Sdumbbell if (dig->coherent_mode) 628254885Sdumbbell args.v2.ucMisc |= PANEL_ENCODER_MISC_COHERENT; 629254885Sdumbbell } 630254885Sdumbbell if (hdmi_detected) 631254885Sdumbbell args.v2.ucMisc |= PANEL_ENCODER_MISC_HDMI_TYPE; 632254885Sdumbbell args.v2.usPixelClock = cpu_to_le16(radeon_encoder->pixel_clock / 10); 633254885Sdumbbell args.v2.ucTruncate = 0; 634254885Sdumbbell args.v2.ucSpatial = 0; 635254885Sdumbbell args.v2.ucTemporal = 0; 636254885Sdumbbell args.v2.ucFRC = 0; 637254885Sdumbbell if (radeon_encoder->devices & (ATOM_DEVICE_LCD_SUPPORT)) { 638254885Sdumbbell if (dig->lcd_misc & ATOM_PANEL_MISC_DUAL) 639254885Sdumbbell args.v2.ucMisc |= PANEL_ENCODER_MISC_DUAL; 640254885Sdumbbell if (dig->lcd_misc & ATOM_PANEL_MISC_SPATIAL) { 641254885Sdumbbell args.v2.ucSpatial = PANEL_ENCODER_SPATIAL_DITHER_EN; 642254885Sdumbbell if (dig->lcd_misc & ATOM_PANEL_MISC_888RGB) 643254885Sdumbbell args.v2.ucSpatial |= PANEL_ENCODER_SPATIAL_DITHER_DEPTH; 644254885Sdumbbell } 645254885Sdumbbell if (dig->lcd_misc & ATOM_PANEL_MISC_TEMPORAL) { 646254885Sdumbbell args.v2.ucTemporal = PANEL_ENCODER_TEMPORAL_DITHER_EN; 647254885Sdumbbell if (dig->lcd_misc & ATOM_PANEL_MISC_888RGB) 648254885Sdumbbell args.v2.ucTemporal |= PANEL_ENCODER_TEMPORAL_DITHER_DEPTH; 649254885Sdumbbell if (((dig->lcd_misc >> ATOM_PANEL_MISC_GREY_LEVEL_SHIFT) & 0x3) == 2) 650254885Sdumbbell args.v2.ucTemporal |= PANEL_ENCODER_TEMPORAL_LEVEL_4; 651254885Sdumbbell } 652254885Sdumbbell } else { 653254885Sdumbbell if (dig->linkb) 654254885Sdumbbell args.v2.ucMisc |= PANEL_ENCODER_MISC_TMDS_LINKB; 655254885Sdumbbell if (radeon_dig_monitor_is_duallink(encoder, radeon_encoder->pixel_clock)) 656254885Sdumbbell args.v2.ucMisc |= PANEL_ENCODER_MISC_DUAL; 657254885Sdumbbell } 658254885Sdumbbell break; 659254885Sdumbbell default: 660254885Sdumbbell DRM_ERROR("Unknown table version %d, %d\n", frev, crev); 661254885Sdumbbell break; 662254885Sdumbbell } 663254885Sdumbbell break; 664254885Sdumbbell default: 665254885Sdumbbell DRM_ERROR("Unknown table version %d, %d\n", frev, crev); 666254885Sdumbbell break; 667254885Sdumbbell } 668254885Sdumbbell 669254885Sdumbbell atom_execute_table(rdev->mode_info.atom_context, index, (uint32_t *)&args); 670254885Sdumbbell} 671254885Sdumbbell 672254885Sdumbbellint 673254885Sdumbbellatombios_get_encoder_mode(struct drm_encoder *encoder) 674254885Sdumbbell{ 675254885Sdumbbell struct radeon_encoder *radeon_encoder = to_radeon_encoder(encoder); 676254885Sdumbbell struct drm_connector *connector; 677254885Sdumbbell struct radeon_connector *radeon_connector; 678254885Sdumbbell struct radeon_connector_atom_dig *dig_connector; 679254885Sdumbbell 680254885Sdumbbell /* dp bridges are always DP */ 681254885Sdumbbell if (radeon_encoder_get_dp_bridge_encoder_id(encoder) != ENCODER_OBJECT_ID_NONE) 682254885Sdumbbell return ATOM_ENCODER_MODE_DP; 683254885Sdumbbell 684254885Sdumbbell /* DVO is always DVO */ 685254885Sdumbbell if ((radeon_encoder->encoder_id == ENCODER_OBJECT_ID_INTERNAL_DVO1) || 686254885Sdumbbell (radeon_encoder->encoder_id == ENCODER_OBJECT_ID_INTERNAL_KLDSCP_DVO1)) 687254885Sdumbbell return ATOM_ENCODER_MODE_DVO; 688254885Sdumbbell 689254885Sdumbbell connector = radeon_get_connector_for_encoder(encoder); 690254885Sdumbbell /* if we don't have an active device yet, just use one of 691254885Sdumbbell * the connectors tied to the encoder. 692254885Sdumbbell */ 693254885Sdumbbell if (!connector) 694254885Sdumbbell connector = radeon_get_connector_for_encoder_init(encoder); 695254885Sdumbbell radeon_connector = to_radeon_connector(connector); 696254885Sdumbbell 697254885Sdumbbell switch (connector->connector_type) { 698254885Sdumbbell case DRM_MODE_CONNECTOR_DVII: 699254885Sdumbbell case DRM_MODE_CONNECTOR_HDMIB: /* HDMI-B is basically DL-DVI; analog works fine */ 700254885Sdumbbell if (drm_detect_hdmi_monitor(radeon_connector->edid) && 701254885Sdumbbell radeon_audio) 702254885Sdumbbell return ATOM_ENCODER_MODE_HDMI; 703254885Sdumbbell else if (radeon_connector->use_digital) 704254885Sdumbbell return ATOM_ENCODER_MODE_DVI; 705254885Sdumbbell else 706254885Sdumbbell return ATOM_ENCODER_MODE_CRT; 707254885Sdumbbell break; 708254885Sdumbbell case DRM_MODE_CONNECTOR_DVID: 709254885Sdumbbell case DRM_MODE_CONNECTOR_HDMIA: 710254885Sdumbbell default: 711254885Sdumbbell if (drm_detect_hdmi_monitor(radeon_connector->edid) && 712254885Sdumbbell radeon_audio) 713254885Sdumbbell return ATOM_ENCODER_MODE_HDMI; 714254885Sdumbbell else 715254885Sdumbbell return ATOM_ENCODER_MODE_DVI; 716254885Sdumbbell break; 717254885Sdumbbell case DRM_MODE_CONNECTOR_LVDS: 718254885Sdumbbell return ATOM_ENCODER_MODE_LVDS; 719254885Sdumbbell break; 720254885Sdumbbell case DRM_MODE_CONNECTOR_DisplayPort: 721254885Sdumbbell dig_connector = radeon_connector->con_priv; 722254885Sdumbbell if ((dig_connector->dp_sink_type == CONNECTOR_OBJECT_ID_DISPLAYPORT) || 723254885Sdumbbell (dig_connector->dp_sink_type == CONNECTOR_OBJECT_ID_eDP)) 724254885Sdumbbell return ATOM_ENCODER_MODE_DP; 725254885Sdumbbell else if (drm_detect_hdmi_monitor(radeon_connector->edid) && 726254885Sdumbbell radeon_audio) 727254885Sdumbbell return ATOM_ENCODER_MODE_HDMI; 728254885Sdumbbell else 729254885Sdumbbell return ATOM_ENCODER_MODE_DVI; 730254885Sdumbbell break; 731254885Sdumbbell case DRM_MODE_CONNECTOR_eDP: 732254885Sdumbbell return ATOM_ENCODER_MODE_DP; 733254885Sdumbbell case DRM_MODE_CONNECTOR_DVIA: 734254885Sdumbbell case DRM_MODE_CONNECTOR_VGA: 735254885Sdumbbell return ATOM_ENCODER_MODE_CRT; 736254885Sdumbbell break; 737254885Sdumbbell case DRM_MODE_CONNECTOR_Composite: 738254885Sdumbbell case DRM_MODE_CONNECTOR_SVIDEO: 739254885Sdumbbell case DRM_MODE_CONNECTOR_9PinDIN: 740254885Sdumbbell /* fix me */ 741254885Sdumbbell return ATOM_ENCODER_MODE_TV; 742254885Sdumbbell /*return ATOM_ENCODER_MODE_CV;*/ 743254885Sdumbbell break; 744254885Sdumbbell } 745254885Sdumbbell} 746254885Sdumbbell 747254885Sdumbbell/* 748254885Sdumbbell * DIG Encoder/Transmitter Setup 749254885Sdumbbell * 750254885Sdumbbell * DCE 3.0/3.1 751254885Sdumbbell * - 2 DIG transmitter blocks. UNIPHY (links A and B) and LVTMA. 752254885Sdumbbell * Supports up to 3 digital outputs 753254885Sdumbbell * - 2 DIG encoder blocks. 754254885Sdumbbell * DIG1 can drive UNIPHY link A or link B 755254885Sdumbbell * DIG2 can drive UNIPHY link B or LVTMA 756254885Sdumbbell * 757254885Sdumbbell * DCE 3.2 758254885Sdumbbell * - 3 DIG transmitter blocks. UNIPHY0/1/2 (links A and B). 759254885Sdumbbell * Supports up to 5 digital outputs 760254885Sdumbbell * - 2 DIG encoder blocks. 761254885Sdumbbell * DIG1/2 can drive UNIPHY0/1/2 link A or link B 762254885Sdumbbell * 763254885Sdumbbell * DCE 4.0/5.0/6.0 764254885Sdumbbell * - 3 DIG transmitter blocks UNIPHY0/1/2 (links A and B). 765254885Sdumbbell * Supports up to 6 digital outputs 766254885Sdumbbell * - 6 DIG encoder blocks. 767254885Sdumbbell * - DIG to PHY mapping is hardcoded 768254885Sdumbbell * DIG1 drives UNIPHY0 link A, A+B 769254885Sdumbbell * DIG2 drives UNIPHY0 link B 770254885Sdumbbell * DIG3 drives UNIPHY1 link A, A+B 771254885Sdumbbell * DIG4 drives UNIPHY1 link B 772254885Sdumbbell * DIG5 drives UNIPHY2 link A, A+B 773254885Sdumbbell * DIG6 drives UNIPHY2 link B 774254885Sdumbbell * 775254885Sdumbbell * DCE 4.1 776254885Sdumbbell * - 3 DIG transmitter blocks UNIPHY0/1/2 (links A and B). 777254885Sdumbbell * Supports up to 6 digital outputs 778254885Sdumbbell * - 2 DIG encoder blocks. 779254885Sdumbbell * llano 780254885Sdumbbell * DIG1/2 can drive UNIPHY0/1/2 link A or link B 781254885Sdumbbell * ontario 782254885Sdumbbell * DIG1 drives UNIPHY0/1/2 link A 783254885Sdumbbell * DIG2 drives UNIPHY0/1/2 link B 784254885Sdumbbell * 785254885Sdumbbell * Routing 786254885Sdumbbell * crtc -> dig encoder -> UNIPHY/LVTMA (1 or 2 links) 787254885Sdumbbell * Examples: 788254885Sdumbbell * crtc0 -> dig2 -> LVTMA links A+B -> TMDS/HDMI 789254885Sdumbbell * crtc1 -> dig1 -> UNIPHY0 link B -> DP 790254885Sdumbbell * crtc0 -> dig1 -> UNIPHY2 link A -> LVDS 791254885Sdumbbell * crtc1 -> dig2 -> UNIPHY1 link B+A -> TMDS/HDMI 792254885Sdumbbell */ 793254885Sdumbbell 794254885Sdumbbellunion dig_encoder_control { 795254885Sdumbbell DIG_ENCODER_CONTROL_PS_ALLOCATION v1; 796254885Sdumbbell DIG_ENCODER_CONTROL_PARAMETERS_V2 v2; 797254885Sdumbbell DIG_ENCODER_CONTROL_PARAMETERS_V3 v3; 798254885Sdumbbell DIG_ENCODER_CONTROL_PARAMETERS_V4 v4; 799254885Sdumbbell}; 800254885Sdumbbell 801254885Sdumbbellvoid 802254885Sdumbbellatombios_dig_encoder_setup(struct drm_encoder *encoder, int action, int panel_mode) 803254885Sdumbbell{ 804254885Sdumbbell struct drm_device *dev = encoder->dev; 805254885Sdumbbell struct radeon_device *rdev = dev->dev_private; 806254885Sdumbbell struct radeon_encoder *radeon_encoder = to_radeon_encoder(encoder); 807254885Sdumbbell struct radeon_encoder_atom_dig *dig = radeon_encoder->enc_priv; 808254885Sdumbbell struct drm_connector *connector = radeon_get_connector_for_encoder(encoder); 809254885Sdumbbell union dig_encoder_control args; 810254885Sdumbbell int index = 0; 811254885Sdumbbell uint8_t frev, crev; 812254885Sdumbbell int dp_clock = 0; 813254885Sdumbbell int dp_lane_count = 0; 814254885Sdumbbell int hpd_id = RADEON_HPD_NONE; 815254885Sdumbbell 816254885Sdumbbell if (connector) { 817254885Sdumbbell struct radeon_connector *radeon_connector = to_radeon_connector(connector); 818254885Sdumbbell struct radeon_connector_atom_dig *dig_connector = 819254885Sdumbbell radeon_connector->con_priv; 820254885Sdumbbell 821254885Sdumbbell dp_clock = dig_connector->dp_clock; 822254885Sdumbbell dp_lane_count = dig_connector->dp_lane_count; 823254885Sdumbbell hpd_id = radeon_connector->hpd.hpd; 824254885Sdumbbell } 825254885Sdumbbell 826254885Sdumbbell /* no dig encoder assigned */ 827254885Sdumbbell if (dig->dig_encoder == -1) 828254885Sdumbbell return; 829254885Sdumbbell 830254885Sdumbbell memset(&args, 0, sizeof(args)); 831254885Sdumbbell 832254885Sdumbbell if (ASIC_IS_DCE4(rdev)) 833254885Sdumbbell index = GetIndexIntoMasterTable(COMMAND, DIGxEncoderControl); 834254885Sdumbbell else { 835254885Sdumbbell if (dig->dig_encoder) 836254885Sdumbbell index = GetIndexIntoMasterTable(COMMAND, DIG2EncoderControl); 837254885Sdumbbell else 838254885Sdumbbell index = GetIndexIntoMasterTable(COMMAND, DIG1EncoderControl); 839254885Sdumbbell } 840254885Sdumbbell 841254885Sdumbbell if (!atom_parse_cmd_header(rdev->mode_info.atom_context, index, &frev, &crev)) 842254885Sdumbbell return; 843254885Sdumbbell 844254885Sdumbbell switch (frev) { 845254885Sdumbbell case 1: 846254885Sdumbbell switch (crev) { 847254885Sdumbbell case 1: 848254885Sdumbbell args.v1.ucAction = action; 849254885Sdumbbell args.v1.usPixelClock = cpu_to_le16(radeon_encoder->pixel_clock / 10); 850254885Sdumbbell if (action == ATOM_ENCODER_CMD_SETUP_PANEL_MODE) 851254885Sdumbbell args.v3.ucPanelMode = panel_mode; 852254885Sdumbbell else 853254885Sdumbbell args.v1.ucEncoderMode = atombios_get_encoder_mode(encoder); 854254885Sdumbbell 855254885Sdumbbell if (ENCODER_MODE_IS_DP(args.v1.ucEncoderMode)) 856254885Sdumbbell args.v1.ucLaneNum = dp_lane_count; 857254885Sdumbbell else if (radeon_dig_monitor_is_duallink(encoder, radeon_encoder->pixel_clock)) 858254885Sdumbbell args.v1.ucLaneNum = 8; 859254885Sdumbbell else 860254885Sdumbbell args.v1.ucLaneNum = 4; 861254885Sdumbbell 862254885Sdumbbell if (ENCODER_MODE_IS_DP(args.v1.ucEncoderMode) && (dp_clock == 270000)) 863254885Sdumbbell args.v1.ucConfig |= ATOM_ENCODER_CONFIG_DPLINKRATE_2_70GHZ; 864254885Sdumbbell switch (radeon_encoder->encoder_id) { 865254885Sdumbbell case ENCODER_OBJECT_ID_INTERNAL_UNIPHY: 866254885Sdumbbell args.v1.ucConfig = ATOM_ENCODER_CONFIG_V2_TRANSMITTER1; 867254885Sdumbbell break; 868254885Sdumbbell case ENCODER_OBJECT_ID_INTERNAL_UNIPHY1: 869254885Sdumbbell case ENCODER_OBJECT_ID_INTERNAL_KLDSCP_LVTMA: 870254885Sdumbbell args.v1.ucConfig = ATOM_ENCODER_CONFIG_V2_TRANSMITTER2; 871254885Sdumbbell break; 872254885Sdumbbell case ENCODER_OBJECT_ID_INTERNAL_UNIPHY2: 873254885Sdumbbell args.v1.ucConfig = ATOM_ENCODER_CONFIG_V2_TRANSMITTER3; 874254885Sdumbbell break; 875254885Sdumbbell } 876254885Sdumbbell if (dig->linkb) 877254885Sdumbbell args.v1.ucConfig |= ATOM_ENCODER_CONFIG_LINKB; 878254885Sdumbbell else 879254885Sdumbbell args.v1.ucConfig |= ATOM_ENCODER_CONFIG_LINKA; 880254885Sdumbbell break; 881254885Sdumbbell case 2: 882254885Sdumbbell case 3: 883254885Sdumbbell args.v3.ucAction = action; 884254885Sdumbbell args.v3.usPixelClock = cpu_to_le16(radeon_encoder->pixel_clock / 10); 885254885Sdumbbell if (action == ATOM_ENCODER_CMD_SETUP_PANEL_MODE) 886254885Sdumbbell args.v3.ucPanelMode = panel_mode; 887254885Sdumbbell else 888254885Sdumbbell args.v3.ucEncoderMode = atombios_get_encoder_mode(encoder); 889254885Sdumbbell 890254885Sdumbbell if (ENCODER_MODE_IS_DP(args.v3.ucEncoderMode)) 891254885Sdumbbell args.v3.ucLaneNum = dp_lane_count; 892254885Sdumbbell else if (radeon_dig_monitor_is_duallink(encoder, radeon_encoder->pixel_clock)) 893254885Sdumbbell args.v3.ucLaneNum = 8; 894254885Sdumbbell else 895254885Sdumbbell args.v3.ucLaneNum = 4; 896254885Sdumbbell 897254885Sdumbbell if (ENCODER_MODE_IS_DP(args.v3.ucEncoderMode) && (dp_clock == 270000)) 898254885Sdumbbell args.v1.ucConfig |= ATOM_ENCODER_CONFIG_V3_DPLINKRATE_2_70GHZ; 899254885Sdumbbell args.v3.acConfig.ucDigSel = dig->dig_encoder; 900254885Sdumbbell args.v3.ucBitPerColor = radeon_atom_get_bpc(encoder); 901254885Sdumbbell break; 902254885Sdumbbell case 4: 903254885Sdumbbell args.v4.ucAction = action; 904254885Sdumbbell args.v4.usPixelClock = cpu_to_le16(radeon_encoder->pixel_clock / 10); 905254885Sdumbbell if (action == ATOM_ENCODER_CMD_SETUP_PANEL_MODE) 906254885Sdumbbell args.v4.ucPanelMode = panel_mode; 907254885Sdumbbell else 908254885Sdumbbell args.v4.ucEncoderMode = atombios_get_encoder_mode(encoder); 909254885Sdumbbell 910254885Sdumbbell if (ENCODER_MODE_IS_DP(args.v4.ucEncoderMode)) 911254885Sdumbbell args.v4.ucLaneNum = dp_lane_count; 912254885Sdumbbell else if (radeon_dig_monitor_is_duallink(encoder, radeon_encoder->pixel_clock)) 913254885Sdumbbell args.v4.ucLaneNum = 8; 914254885Sdumbbell else 915254885Sdumbbell args.v4.ucLaneNum = 4; 916254885Sdumbbell 917254885Sdumbbell if (ENCODER_MODE_IS_DP(args.v4.ucEncoderMode)) { 918254885Sdumbbell if (dp_clock == 270000) 919254885Sdumbbell args.v1.ucConfig |= ATOM_ENCODER_CONFIG_V4_DPLINKRATE_2_70GHZ; 920254885Sdumbbell else if (dp_clock == 540000) 921254885Sdumbbell args.v1.ucConfig |= ATOM_ENCODER_CONFIG_V4_DPLINKRATE_5_40GHZ; 922254885Sdumbbell } 923254885Sdumbbell args.v4.acConfig.ucDigSel = dig->dig_encoder; 924254885Sdumbbell args.v4.ucBitPerColor = radeon_atom_get_bpc(encoder); 925254885Sdumbbell if (hpd_id == RADEON_HPD_NONE) 926254885Sdumbbell args.v4.ucHPD_ID = 0; 927254885Sdumbbell else 928254885Sdumbbell args.v4.ucHPD_ID = hpd_id + 1; 929254885Sdumbbell break; 930254885Sdumbbell default: 931254885Sdumbbell DRM_ERROR("Unknown table version %d, %d\n", frev, crev); 932254885Sdumbbell break; 933254885Sdumbbell } 934254885Sdumbbell break; 935254885Sdumbbell default: 936254885Sdumbbell DRM_ERROR("Unknown table version %d, %d\n", frev, crev); 937254885Sdumbbell break; 938254885Sdumbbell } 939254885Sdumbbell 940254885Sdumbbell atom_execute_table(rdev->mode_info.atom_context, index, (uint32_t *)&args); 941254885Sdumbbell 942254885Sdumbbell} 943254885Sdumbbell 944254885Sdumbbellunion dig_transmitter_control { 945254885Sdumbbell DIG_TRANSMITTER_CONTROL_PS_ALLOCATION v1; 946254885Sdumbbell DIG_TRANSMITTER_CONTROL_PARAMETERS_V2 v2; 947254885Sdumbbell DIG_TRANSMITTER_CONTROL_PARAMETERS_V3 v3; 948254885Sdumbbell DIG_TRANSMITTER_CONTROL_PARAMETERS_V4 v4; 949254885Sdumbbell DIG_TRANSMITTER_CONTROL_PARAMETERS_V1_5 v5; 950254885Sdumbbell}; 951254885Sdumbbell 952254885Sdumbbellvoid 953254885Sdumbbellatombios_dig_transmitter_setup(struct drm_encoder *encoder, int action, uint8_t lane_num, uint8_t lane_set) 954254885Sdumbbell{ 955254885Sdumbbell struct drm_device *dev = encoder->dev; 956254885Sdumbbell struct radeon_device *rdev = dev->dev_private; 957254885Sdumbbell struct radeon_encoder *radeon_encoder = to_radeon_encoder(encoder); 958254885Sdumbbell struct radeon_encoder_atom_dig *dig = radeon_encoder->enc_priv; 959254885Sdumbbell struct drm_connector *connector; 960254885Sdumbbell union dig_transmitter_control args; 961254885Sdumbbell int index = 0; 962254885Sdumbbell uint8_t frev, crev; 963254885Sdumbbell bool is_dp = false; 964254885Sdumbbell int pll_id = 0; 965254885Sdumbbell int dp_clock = 0; 966254885Sdumbbell int dp_lane_count = 0; 967254885Sdumbbell int connector_object_id = 0; 968254885Sdumbbell int igp_lane_info = 0; 969254885Sdumbbell int dig_encoder = dig->dig_encoder; 970254885Sdumbbell int hpd_id = RADEON_HPD_NONE; 971254885Sdumbbell 972254885Sdumbbell if (action == ATOM_TRANSMITTER_ACTION_INIT) { 973254885Sdumbbell connector = radeon_get_connector_for_encoder_init(encoder); 974254885Sdumbbell /* just needed to avoid bailing in the encoder check. the encoder 975254885Sdumbbell * isn't used for init 976254885Sdumbbell */ 977254885Sdumbbell dig_encoder = 0; 978254885Sdumbbell } else 979254885Sdumbbell connector = radeon_get_connector_for_encoder(encoder); 980254885Sdumbbell 981254885Sdumbbell if (connector) { 982254885Sdumbbell struct radeon_connector *radeon_connector = to_radeon_connector(connector); 983254885Sdumbbell struct radeon_connector_atom_dig *dig_connector = 984254885Sdumbbell radeon_connector->con_priv; 985254885Sdumbbell 986254885Sdumbbell hpd_id = radeon_connector->hpd.hpd; 987254885Sdumbbell dp_clock = dig_connector->dp_clock; 988254885Sdumbbell dp_lane_count = dig_connector->dp_lane_count; 989254885Sdumbbell connector_object_id = 990254885Sdumbbell (radeon_connector->connector_object_id & OBJECT_ID_MASK) >> OBJECT_ID_SHIFT; 991254885Sdumbbell igp_lane_info = dig_connector->igp_lane_info; 992254885Sdumbbell } 993254885Sdumbbell 994254885Sdumbbell if (encoder->crtc) { 995254885Sdumbbell struct radeon_crtc *radeon_crtc = to_radeon_crtc(encoder->crtc); 996254885Sdumbbell pll_id = radeon_crtc->pll_id; 997254885Sdumbbell } 998254885Sdumbbell 999254885Sdumbbell /* no dig encoder assigned */ 1000254885Sdumbbell if (dig_encoder == -1) 1001254885Sdumbbell return; 1002254885Sdumbbell 1003254885Sdumbbell if (ENCODER_MODE_IS_DP(atombios_get_encoder_mode(encoder))) 1004254885Sdumbbell is_dp = true; 1005254885Sdumbbell 1006254885Sdumbbell memset(&args, 0, sizeof(args)); 1007254885Sdumbbell 1008254885Sdumbbell switch (radeon_encoder->encoder_id) { 1009254885Sdumbbell case ENCODER_OBJECT_ID_INTERNAL_KLDSCP_DVO1: 1010254885Sdumbbell index = GetIndexIntoMasterTable(COMMAND, DVOOutputControl); 1011254885Sdumbbell break; 1012254885Sdumbbell case ENCODER_OBJECT_ID_INTERNAL_UNIPHY: 1013254885Sdumbbell case ENCODER_OBJECT_ID_INTERNAL_UNIPHY1: 1014254885Sdumbbell case ENCODER_OBJECT_ID_INTERNAL_UNIPHY2: 1015254885Sdumbbell index = GetIndexIntoMasterTable(COMMAND, UNIPHYTransmitterControl); 1016254885Sdumbbell break; 1017254885Sdumbbell case ENCODER_OBJECT_ID_INTERNAL_KLDSCP_LVTMA: 1018254885Sdumbbell index = GetIndexIntoMasterTable(COMMAND, LVTMATransmitterControl); 1019254885Sdumbbell break; 1020254885Sdumbbell } 1021254885Sdumbbell 1022254885Sdumbbell if (!atom_parse_cmd_header(rdev->mode_info.atom_context, index, &frev, &crev)) 1023254885Sdumbbell return; 1024254885Sdumbbell 1025254885Sdumbbell switch (frev) { 1026254885Sdumbbell case 1: 1027254885Sdumbbell switch (crev) { 1028254885Sdumbbell case 1: 1029254885Sdumbbell args.v1.ucAction = action; 1030254885Sdumbbell if (action == ATOM_TRANSMITTER_ACTION_INIT) { 1031254885Sdumbbell args.v1.usInitInfo = cpu_to_le16(connector_object_id); 1032254885Sdumbbell } else if (action == ATOM_TRANSMITTER_ACTION_SETUP_VSEMPH) { 1033254885Sdumbbell args.v1.asMode.ucLaneSel = lane_num; 1034254885Sdumbbell args.v1.asMode.ucLaneSet = lane_set; 1035254885Sdumbbell } else { 1036254885Sdumbbell if (is_dp) 1037254885Sdumbbell args.v1.usPixelClock = cpu_to_le16(dp_clock / 10); 1038254885Sdumbbell else if (radeon_dig_monitor_is_duallink(encoder, radeon_encoder->pixel_clock)) 1039254885Sdumbbell args.v1.usPixelClock = cpu_to_le16((radeon_encoder->pixel_clock / 2) / 10); 1040254885Sdumbbell else 1041254885Sdumbbell args.v1.usPixelClock = cpu_to_le16(radeon_encoder->pixel_clock / 10); 1042254885Sdumbbell } 1043254885Sdumbbell 1044254885Sdumbbell args.v1.ucConfig = ATOM_TRANSMITTER_CONFIG_CLKSRC_PPLL; 1045254885Sdumbbell 1046254885Sdumbbell if (dig_encoder) 1047254885Sdumbbell args.v1.ucConfig |= ATOM_TRANSMITTER_CONFIG_DIG2_ENCODER; 1048254885Sdumbbell else 1049254885Sdumbbell args.v1.ucConfig |= ATOM_TRANSMITTER_CONFIG_DIG1_ENCODER; 1050254885Sdumbbell 1051254885Sdumbbell if ((rdev->flags & RADEON_IS_IGP) && 1052254885Sdumbbell (radeon_encoder->encoder_id == ENCODER_OBJECT_ID_INTERNAL_UNIPHY)) { 1053254885Sdumbbell if (is_dp || 1054254885Sdumbbell !radeon_dig_monitor_is_duallink(encoder, radeon_encoder->pixel_clock)) { 1055254885Sdumbbell if (igp_lane_info & 0x1) 1056254885Sdumbbell args.v1.ucConfig |= ATOM_TRANSMITTER_CONFIG_LANE_0_3; 1057254885Sdumbbell else if (igp_lane_info & 0x2) 1058254885Sdumbbell args.v1.ucConfig |= ATOM_TRANSMITTER_CONFIG_LANE_4_7; 1059254885Sdumbbell else if (igp_lane_info & 0x4) 1060254885Sdumbbell args.v1.ucConfig |= ATOM_TRANSMITTER_CONFIG_LANE_8_11; 1061254885Sdumbbell else if (igp_lane_info & 0x8) 1062254885Sdumbbell args.v1.ucConfig |= ATOM_TRANSMITTER_CONFIG_LANE_12_15; 1063254885Sdumbbell } else { 1064254885Sdumbbell if (igp_lane_info & 0x3) 1065254885Sdumbbell args.v1.ucConfig |= ATOM_TRANSMITTER_CONFIG_LANE_0_7; 1066254885Sdumbbell else if (igp_lane_info & 0xc) 1067254885Sdumbbell args.v1.ucConfig |= ATOM_TRANSMITTER_CONFIG_LANE_8_15; 1068254885Sdumbbell } 1069254885Sdumbbell } 1070254885Sdumbbell 1071254885Sdumbbell if (dig->linkb) 1072254885Sdumbbell args.v1.ucConfig |= ATOM_TRANSMITTER_CONFIG_LINKB; 1073254885Sdumbbell else 1074254885Sdumbbell args.v1.ucConfig |= ATOM_TRANSMITTER_CONFIG_LINKA; 1075254885Sdumbbell 1076254885Sdumbbell if (is_dp) 1077254885Sdumbbell args.v1.ucConfig |= ATOM_TRANSMITTER_CONFIG_COHERENT; 1078254885Sdumbbell else if (radeon_encoder->devices & (ATOM_DEVICE_DFP_SUPPORT)) { 1079254885Sdumbbell if (dig->coherent_mode) 1080254885Sdumbbell args.v1.ucConfig |= ATOM_TRANSMITTER_CONFIG_COHERENT; 1081254885Sdumbbell if (radeon_dig_monitor_is_duallink(encoder, radeon_encoder->pixel_clock)) 1082254885Sdumbbell args.v1.ucConfig |= ATOM_TRANSMITTER_CONFIG_8LANE_LINK; 1083254885Sdumbbell } 1084254885Sdumbbell break; 1085254885Sdumbbell case 2: 1086254885Sdumbbell args.v2.ucAction = action; 1087254885Sdumbbell if (action == ATOM_TRANSMITTER_ACTION_INIT) { 1088254885Sdumbbell args.v2.usInitInfo = cpu_to_le16(connector_object_id); 1089254885Sdumbbell } else if (action == ATOM_TRANSMITTER_ACTION_SETUP_VSEMPH) { 1090254885Sdumbbell args.v2.asMode.ucLaneSel = lane_num; 1091254885Sdumbbell args.v2.asMode.ucLaneSet = lane_set; 1092254885Sdumbbell } else { 1093254885Sdumbbell if (is_dp) 1094254885Sdumbbell args.v2.usPixelClock = cpu_to_le16(dp_clock / 10); 1095254885Sdumbbell else if (radeon_dig_monitor_is_duallink(encoder, radeon_encoder->pixel_clock)) 1096254885Sdumbbell args.v2.usPixelClock = cpu_to_le16((radeon_encoder->pixel_clock / 2) / 10); 1097254885Sdumbbell else 1098254885Sdumbbell args.v2.usPixelClock = cpu_to_le16(radeon_encoder->pixel_clock / 10); 1099254885Sdumbbell } 1100254885Sdumbbell 1101254885Sdumbbell args.v2.acConfig.ucEncoderSel = dig_encoder; 1102254885Sdumbbell if (dig->linkb) 1103254885Sdumbbell args.v2.acConfig.ucLinkSel = 1; 1104254885Sdumbbell 1105254885Sdumbbell switch (radeon_encoder->encoder_id) { 1106254885Sdumbbell case ENCODER_OBJECT_ID_INTERNAL_UNIPHY: 1107254885Sdumbbell args.v2.acConfig.ucTransmitterSel = 0; 1108254885Sdumbbell break; 1109254885Sdumbbell case ENCODER_OBJECT_ID_INTERNAL_UNIPHY1: 1110254885Sdumbbell args.v2.acConfig.ucTransmitterSel = 1; 1111254885Sdumbbell break; 1112254885Sdumbbell case ENCODER_OBJECT_ID_INTERNAL_UNIPHY2: 1113254885Sdumbbell args.v2.acConfig.ucTransmitterSel = 2; 1114254885Sdumbbell break; 1115254885Sdumbbell } 1116254885Sdumbbell 1117254885Sdumbbell if (is_dp) { 1118254885Sdumbbell args.v2.acConfig.fCoherentMode = 1; 1119254885Sdumbbell args.v2.acConfig.fDPConnector = 1; 1120254885Sdumbbell } else if (radeon_encoder->devices & (ATOM_DEVICE_DFP_SUPPORT)) { 1121254885Sdumbbell if (dig->coherent_mode) 1122254885Sdumbbell args.v2.acConfig.fCoherentMode = 1; 1123254885Sdumbbell if (radeon_dig_monitor_is_duallink(encoder, radeon_encoder->pixel_clock)) 1124254885Sdumbbell args.v2.acConfig.fDualLinkConnector = 1; 1125254885Sdumbbell } 1126254885Sdumbbell break; 1127254885Sdumbbell case 3: 1128254885Sdumbbell args.v3.ucAction = action; 1129254885Sdumbbell if (action == ATOM_TRANSMITTER_ACTION_INIT) { 1130254885Sdumbbell args.v3.usInitInfo = cpu_to_le16(connector_object_id); 1131254885Sdumbbell } else if (action == ATOM_TRANSMITTER_ACTION_SETUP_VSEMPH) { 1132254885Sdumbbell args.v3.asMode.ucLaneSel = lane_num; 1133254885Sdumbbell args.v3.asMode.ucLaneSet = lane_set; 1134254885Sdumbbell } else { 1135254885Sdumbbell if (is_dp) 1136254885Sdumbbell args.v3.usPixelClock = cpu_to_le16(dp_clock / 10); 1137254885Sdumbbell else if (radeon_dig_monitor_is_duallink(encoder, radeon_encoder->pixel_clock)) 1138254885Sdumbbell args.v3.usPixelClock = cpu_to_le16((radeon_encoder->pixel_clock / 2) / 10); 1139254885Sdumbbell else 1140254885Sdumbbell args.v3.usPixelClock = cpu_to_le16(radeon_encoder->pixel_clock / 10); 1141254885Sdumbbell } 1142254885Sdumbbell 1143254885Sdumbbell if (is_dp) 1144254885Sdumbbell args.v3.ucLaneNum = dp_lane_count; 1145254885Sdumbbell else if (radeon_dig_monitor_is_duallink(encoder, radeon_encoder->pixel_clock)) 1146254885Sdumbbell args.v3.ucLaneNum = 8; 1147254885Sdumbbell else 1148254885Sdumbbell args.v3.ucLaneNum = 4; 1149254885Sdumbbell 1150254885Sdumbbell if (dig->linkb) 1151254885Sdumbbell args.v3.acConfig.ucLinkSel = 1; 1152254885Sdumbbell if (dig_encoder & 1) 1153254885Sdumbbell args.v3.acConfig.ucEncoderSel = 1; 1154254885Sdumbbell 1155254885Sdumbbell /* Select the PLL for the PHY 1156254885Sdumbbell * DP PHY should be clocked from external src if there is 1157254885Sdumbbell * one. 1158254885Sdumbbell */ 1159254885Sdumbbell /* On DCE4, if there is an external clock, it generates the DP ref clock */ 1160254885Sdumbbell if (is_dp && rdev->clock.dp_extclk) 1161254885Sdumbbell args.v3.acConfig.ucRefClkSource = 2; /* external src */ 1162254885Sdumbbell else 1163254885Sdumbbell args.v3.acConfig.ucRefClkSource = pll_id; 1164254885Sdumbbell 1165254885Sdumbbell switch (radeon_encoder->encoder_id) { 1166254885Sdumbbell case ENCODER_OBJECT_ID_INTERNAL_UNIPHY: 1167254885Sdumbbell args.v3.acConfig.ucTransmitterSel = 0; 1168254885Sdumbbell break; 1169254885Sdumbbell case ENCODER_OBJECT_ID_INTERNAL_UNIPHY1: 1170254885Sdumbbell args.v3.acConfig.ucTransmitterSel = 1; 1171254885Sdumbbell break; 1172254885Sdumbbell case ENCODER_OBJECT_ID_INTERNAL_UNIPHY2: 1173254885Sdumbbell args.v3.acConfig.ucTransmitterSel = 2; 1174254885Sdumbbell break; 1175254885Sdumbbell } 1176254885Sdumbbell 1177254885Sdumbbell if (is_dp) 1178254885Sdumbbell args.v3.acConfig.fCoherentMode = 1; /* DP requires coherent */ 1179254885Sdumbbell else if (radeon_encoder->devices & (ATOM_DEVICE_DFP_SUPPORT)) { 1180254885Sdumbbell if (dig->coherent_mode) 1181254885Sdumbbell args.v3.acConfig.fCoherentMode = 1; 1182254885Sdumbbell if (radeon_dig_monitor_is_duallink(encoder, radeon_encoder->pixel_clock)) 1183254885Sdumbbell args.v3.acConfig.fDualLinkConnector = 1; 1184254885Sdumbbell } 1185254885Sdumbbell break; 1186254885Sdumbbell case 4: 1187254885Sdumbbell args.v4.ucAction = action; 1188254885Sdumbbell if (action == ATOM_TRANSMITTER_ACTION_INIT) { 1189254885Sdumbbell args.v4.usInitInfo = cpu_to_le16(connector_object_id); 1190254885Sdumbbell } else if (action == ATOM_TRANSMITTER_ACTION_SETUP_VSEMPH) { 1191254885Sdumbbell args.v4.asMode.ucLaneSel = lane_num; 1192254885Sdumbbell args.v4.asMode.ucLaneSet = lane_set; 1193254885Sdumbbell } else { 1194254885Sdumbbell if (is_dp) 1195254885Sdumbbell args.v4.usPixelClock = cpu_to_le16(dp_clock / 10); 1196254885Sdumbbell else if (radeon_dig_monitor_is_duallink(encoder, radeon_encoder->pixel_clock)) 1197254885Sdumbbell args.v4.usPixelClock = cpu_to_le16((radeon_encoder->pixel_clock / 2) / 10); 1198254885Sdumbbell else 1199254885Sdumbbell args.v4.usPixelClock = cpu_to_le16(radeon_encoder->pixel_clock / 10); 1200254885Sdumbbell } 1201254885Sdumbbell 1202254885Sdumbbell if (is_dp) 1203254885Sdumbbell args.v4.ucLaneNum = dp_lane_count; 1204254885Sdumbbell else if (radeon_dig_monitor_is_duallink(encoder, radeon_encoder->pixel_clock)) 1205254885Sdumbbell args.v4.ucLaneNum = 8; 1206254885Sdumbbell else 1207254885Sdumbbell args.v4.ucLaneNum = 4; 1208254885Sdumbbell 1209254885Sdumbbell if (dig->linkb) 1210254885Sdumbbell args.v4.acConfig.ucLinkSel = 1; 1211254885Sdumbbell if (dig_encoder & 1) 1212254885Sdumbbell args.v4.acConfig.ucEncoderSel = 1; 1213254885Sdumbbell 1214254885Sdumbbell /* Select the PLL for the PHY 1215254885Sdumbbell * DP PHY should be clocked from external src if there is 1216254885Sdumbbell * one. 1217254885Sdumbbell */ 1218254885Sdumbbell /* On DCE5 DCPLL usually generates the DP ref clock */ 1219254885Sdumbbell if (is_dp) { 1220254885Sdumbbell if (rdev->clock.dp_extclk) 1221254885Sdumbbell args.v4.acConfig.ucRefClkSource = ENCODER_REFCLK_SRC_EXTCLK; 1222254885Sdumbbell else 1223254885Sdumbbell args.v4.acConfig.ucRefClkSource = ENCODER_REFCLK_SRC_DCPLL; 1224254885Sdumbbell } else 1225254885Sdumbbell args.v4.acConfig.ucRefClkSource = pll_id; 1226254885Sdumbbell 1227254885Sdumbbell switch (radeon_encoder->encoder_id) { 1228254885Sdumbbell case ENCODER_OBJECT_ID_INTERNAL_UNIPHY: 1229254885Sdumbbell args.v4.acConfig.ucTransmitterSel = 0; 1230254885Sdumbbell break; 1231254885Sdumbbell case ENCODER_OBJECT_ID_INTERNAL_UNIPHY1: 1232254885Sdumbbell args.v4.acConfig.ucTransmitterSel = 1; 1233254885Sdumbbell break; 1234254885Sdumbbell case ENCODER_OBJECT_ID_INTERNAL_UNIPHY2: 1235254885Sdumbbell args.v4.acConfig.ucTransmitterSel = 2; 1236254885Sdumbbell break; 1237254885Sdumbbell } 1238254885Sdumbbell 1239254885Sdumbbell if (is_dp) 1240254885Sdumbbell args.v4.acConfig.fCoherentMode = 1; /* DP requires coherent */ 1241254885Sdumbbell else if (radeon_encoder->devices & (ATOM_DEVICE_DFP_SUPPORT)) { 1242254885Sdumbbell if (dig->coherent_mode) 1243254885Sdumbbell args.v4.acConfig.fCoherentMode = 1; 1244254885Sdumbbell if (radeon_dig_monitor_is_duallink(encoder, radeon_encoder->pixel_clock)) 1245254885Sdumbbell args.v4.acConfig.fDualLinkConnector = 1; 1246254885Sdumbbell } 1247254885Sdumbbell break; 1248254885Sdumbbell case 5: 1249254885Sdumbbell args.v5.ucAction = action; 1250254885Sdumbbell if (is_dp) 1251254885Sdumbbell args.v5.usSymClock = cpu_to_le16(dp_clock / 10); 1252254885Sdumbbell else 1253254885Sdumbbell args.v5.usSymClock = cpu_to_le16(radeon_encoder->pixel_clock / 10); 1254254885Sdumbbell 1255254885Sdumbbell switch (radeon_encoder->encoder_id) { 1256254885Sdumbbell case ENCODER_OBJECT_ID_INTERNAL_UNIPHY: 1257254885Sdumbbell if (dig->linkb) 1258254885Sdumbbell args.v5.ucPhyId = ATOM_PHY_ID_UNIPHYB; 1259254885Sdumbbell else 1260254885Sdumbbell args.v5.ucPhyId = ATOM_PHY_ID_UNIPHYA; 1261254885Sdumbbell break; 1262254885Sdumbbell case ENCODER_OBJECT_ID_INTERNAL_UNIPHY1: 1263254885Sdumbbell if (dig->linkb) 1264254885Sdumbbell args.v5.ucPhyId = ATOM_PHY_ID_UNIPHYD; 1265254885Sdumbbell else 1266254885Sdumbbell args.v5.ucPhyId = ATOM_PHY_ID_UNIPHYC; 1267254885Sdumbbell break; 1268254885Sdumbbell case ENCODER_OBJECT_ID_INTERNAL_UNIPHY2: 1269254885Sdumbbell if (dig->linkb) 1270254885Sdumbbell args.v5.ucPhyId = ATOM_PHY_ID_UNIPHYF; 1271254885Sdumbbell else 1272254885Sdumbbell args.v5.ucPhyId = ATOM_PHY_ID_UNIPHYE; 1273254885Sdumbbell break; 1274254885Sdumbbell } 1275254885Sdumbbell if (is_dp) 1276254885Sdumbbell args.v5.ucLaneNum = dp_lane_count; 1277254885Sdumbbell else if (radeon_encoder->pixel_clock > 165000) 1278254885Sdumbbell args.v5.ucLaneNum = 8; 1279254885Sdumbbell else 1280254885Sdumbbell args.v5.ucLaneNum = 4; 1281254885Sdumbbell args.v5.ucConnObjId = connector_object_id; 1282254885Sdumbbell args.v5.ucDigMode = atombios_get_encoder_mode(encoder); 1283254885Sdumbbell 1284254885Sdumbbell if (is_dp && rdev->clock.dp_extclk) 1285254885Sdumbbell args.v5.asConfig.ucPhyClkSrcId = ENCODER_REFCLK_SRC_EXTCLK; 1286254885Sdumbbell else 1287254885Sdumbbell args.v5.asConfig.ucPhyClkSrcId = pll_id; 1288254885Sdumbbell 1289254885Sdumbbell if (is_dp) 1290254885Sdumbbell args.v5.asConfig.ucCoherentMode = 1; /* DP requires coherent */ 1291254885Sdumbbell else if (radeon_encoder->devices & (ATOM_DEVICE_DFP_SUPPORT)) { 1292254885Sdumbbell if (dig->coherent_mode) 1293254885Sdumbbell args.v5.asConfig.ucCoherentMode = 1; 1294254885Sdumbbell } 1295254885Sdumbbell if (hpd_id == RADEON_HPD_NONE) 1296254885Sdumbbell args.v5.asConfig.ucHPDSel = 0; 1297254885Sdumbbell else 1298254885Sdumbbell args.v5.asConfig.ucHPDSel = hpd_id + 1; 1299254885Sdumbbell args.v5.ucDigEncoderSel = 1 << dig_encoder; 1300254885Sdumbbell args.v5.ucDPLaneSet = lane_set; 1301254885Sdumbbell break; 1302254885Sdumbbell default: 1303254885Sdumbbell DRM_ERROR("Unknown table version %d, %d\n", frev, crev); 1304254885Sdumbbell break; 1305254885Sdumbbell } 1306254885Sdumbbell break; 1307254885Sdumbbell default: 1308254885Sdumbbell DRM_ERROR("Unknown table version %d, %d\n", frev, crev); 1309254885Sdumbbell break; 1310254885Sdumbbell } 1311254885Sdumbbell 1312254885Sdumbbell atom_execute_table(rdev->mode_info.atom_context, index, (uint32_t *)&args); 1313254885Sdumbbell} 1314254885Sdumbbell 1315254885Sdumbbellbool 1316254885Sdumbbellatombios_set_edp_panel_power(struct drm_connector *connector, int action) 1317254885Sdumbbell{ 1318254885Sdumbbell struct radeon_connector *radeon_connector = to_radeon_connector(connector); 1319254885Sdumbbell struct drm_device *dev = radeon_connector->base.dev; 1320254885Sdumbbell struct radeon_device *rdev = dev->dev_private; 1321254885Sdumbbell union dig_transmitter_control args; 1322254885Sdumbbell int index = GetIndexIntoMasterTable(COMMAND, UNIPHYTransmitterControl); 1323254885Sdumbbell uint8_t frev, crev; 1324254885Sdumbbell 1325254885Sdumbbell if (connector->connector_type != DRM_MODE_CONNECTOR_eDP) 1326254885Sdumbbell goto done; 1327254885Sdumbbell 1328254885Sdumbbell if (!ASIC_IS_DCE4(rdev)) 1329254885Sdumbbell goto done; 1330254885Sdumbbell 1331254885Sdumbbell if ((action != ATOM_TRANSMITTER_ACTION_POWER_ON) && 1332254885Sdumbbell (action != ATOM_TRANSMITTER_ACTION_POWER_OFF)) 1333254885Sdumbbell goto done; 1334254885Sdumbbell 1335254885Sdumbbell if (!atom_parse_cmd_header(rdev->mode_info.atom_context, index, &frev, &crev)) 1336254885Sdumbbell goto done; 1337254885Sdumbbell 1338254885Sdumbbell memset(&args, 0, sizeof(args)); 1339254885Sdumbbell 1340254885Sdumbbell args.v1.ucAction = action; 1341254885Sdumbbell 1342254885Sdumbbell atom_execute_table(rdev->mode_info.atom_context, index, (uint32_t *)&args); 1343254885Sdumbbell 1344254885Sdumbbell /* wait for the panel to power up */ 1345254885Sdumbbell if (action == ATOM_TRANSMITTER_ACTION_POWER_ON) { 1346254885Sdumbbell int i; 1347254885Sdumbbell 1348254885Sdumbbell for (i = 0; i < 300; i++) { 1349254885Sdumbbell if (radeon_hpd_sense(rdev, radeon_connector->hpd.hpd)) 1350254885Sdumbbell return true; 1351280183Sdumbbell mdelay(1); 1352254885Sdumbbell } 1353254885Sdumbbell return false; 1354254885Sdumbbell } 1355254885Sdumbbelldone: 1356254885Sdumbbell return true; 1357254885Sdumbbell} 1358254885Sdumbbell 1359254885Sdumbbellunion external_encoder_control { 1360254885Sdumbbell EXTERNAL_ENCODER_CONTROL_PS_ALLOCATION v1; 1361254885Sdumbbell EXTERNAL_ENCODER_CONTROL_PS_ALLOCATION_V3 v3; 1362254885Sdumbbell}; 1363254885Sdumbbell 1364254885Sdumbbellstatic void 1365254885Sdumbbellatombios_external_encoder_setup(struct drm_encoder *encoder, 1366254885Sdumbbell struct drm_encoder *ext_encoder, 1367254885Sdumbbell int action) 1368254885Sdumbbell{ 1369254885Sdumbbell struct drm_device *dev = encoder->dev; 1370254885Sdumbbell struct radeon_device *rdev = dev->dev_private; 1371254885Sdumbbell struct radeon_encoder *radeon_encoder = to_radeon_encoder(encoder); 1372254885Sdumbbell struct radeon_encoder *ext_radeon_encoder = to_radeon_encoder(ext_encoder); 1373254885Sdumbbell union external_encoder_control args; 1374254885Sdumbbell struct drm_connector *connector; 1375254885Sdumbbell int index = GetIndexIntoMasterTable(COMMAND, ExternalEncoderControl); 1376254885Sdumbbell u8 frev, crev; 1377254885Sdumbbell int dp_clock = 0; 1378254885Sdumbbell int dp_lane_count = 0; 1379254885Sdumbbell int connector_object_id = 0; 1380254885Sdumbbell u32 ext_enum = (ext_radeon_encoder->encoder_enum & ENUM_ID_MASK) >> ENUM_ID_SHIFT; 1381254885Sdumbbell 1382254885Sdumbbell if (action == EXTERNAL_ENCODER_ACTION_V3_ENCODER_INIT) 1383254885Sdumbbell connector = radeon_get_connector_for_encoder_init(encoder); 1384254885Sdumbbell else 1385254885Sdumbbell connector = radeon_get_connector_for_encoder(encoder); 1386254885Sdumbbell 1387254885Sdumbbell if (connector) { 1388254885Sdumbbell struct radeon_connector *radeon_connector = to_radeon_connector(connector); 1389254885Sdumbbell struct radeon_connector_atom_dig *dig_connector = 1390254885Sdumbbell radeon_connector->con_priv; 1391254885Sdumbbell 1392254885Sdumbbell dp_clock = dig_connector->dp_clock; 1393254885Sdumbbell dp_lane_count = dig_connector->dp_lane_count; 1394254885Sdumbbell connector_object_id = 1395254885Sdumbbell (radeon_connector->connector_object_id & OBJECT_ID_MASK) >> OBJECT_ID_SHIFT; 1396254885Sdumbbell } 1397254885Sdumbbell 1398254885Sdumbbell memset(&args, 0, sizeof(args)); 1399254885Sdumbbell 1400254885Sdumbbell if (!atom_parse_cmd_header(rdev->mode_info.atom_context, index, &frev, &crev)) 1401254885Sdumbbell return; 1402254885Sdumbbell 1403254885Sdumbbell switch (frev) { 1404254885Sdumbbell case 1: 1405254885Sdumbbell /* no params on frev 1 */ 1406254885Sdumbbell break; 1407254885Sdumbbell case 2: 1408254885Sdumbbell switch (crev) { 1409254885Sdumbbell case 1: 1410254885Sdumbbell case 2: 1411254885Sdumbbell args.v1.sDigEncoder.ucAction = action; 1412254885Sdumbbell args.v1.sDigEncoder.usPixelClock = cpu_to_le16(radeon_encoder->pixel_clock / 10); 1413254885Sdumbbell args.v1.sDigEncoder.ucEncoderMode = atombios_get_encoder_mode(encoder); 1414254885Sdumbbell 1415254885Sdumbbell if (ENCODER_MODE_IS_DP(args.v1.sDigEncoder.ucEncoderMode)) { 1416254885Sdumbbell if (dp_clock == 270000) 1417254885Sdumbbell args.v1.sDigEncoder.ucConfig |= ATOM_ENCODER_CONFIG_DPLINKRATE_2_70GHZ; 1418254885Sdumbbell args.v1.sDigEncoder.ucLaneNum = dp_lane_count; 1419254885Sdumbbell } else if (radeon_dig_monitor_is_duallink(encoder, radeon_encoder->pixel_clock)) 1420254885Sdumbbell args.v1.sDigEncoder.ucLaneNum = 8; 1421254885Sdumbbell else 1422254885Sdumbbell args.v1.sDigEncoder.ucLaneNum = 4; 1423254885Sdumbbell break; 1424254885Sdumbbell case 3: 1425254885Sdumbbell args.v3.sExtEncoder.ucAction = action; 1426254885Sdumbbell if (action == EXTERNAL_ENCODER_ACTION_V3_ENCODER_INIT) 1427254885Sdumbbell args.v3.sExtEncoder.usConnectorId = cpu_to_le16(connector_object_id); 1428254885Sdumbbell else 1429254885Sdumbbell args.v3.sExtEncoder.usPixelClock = cpu_to_le16(radeon_encoder->pixel_clock / 10); 1430254885Sdumbbell args.v3.sExtEncoder.ucEncoderMode = atombios_get_encoder_mode(encoder); 1431254885Sdumbbell 1432254885Sdumbbell if (ENCODER_MODE_IS_DP(args.v3.sExtEncoder.ucEncoderMode)) { 1433254885Sdumbbell if (dp_clock == 270000) 1434254885Sdumbbell args.v3.sExtEncoder.ucConfig |= EXTERNAL_ENCODER_CONFIG_V3_DPLINKRATE_2_70GHZ; 1435254885Sdumbbell else if (dp_clock == 540000) 1436254885Sdumbbell args.v3.sExtEncoder.ucConfig |= EXTERNAL_ENCODER_CONFIG_V3_DPLINKRATE_5_40GHZ; 1437254885Sdumbbell args.v3.sExtEncoder.ucLaneNum = dp_lane_count; 1438254885Sdumbbell } else if (radeon_dig_monitor_is_duallink(encoder, radeon_encoder->pixel_clock)) 1439254885Sdumbbell args.v3.sExtEncoder.ucLaneNum = 8; 1440254885Sdumbbell else 1441254885Sdumbbell args.v3.sExtEncoder.ucLaneNum = 4; 1442254885Sdumbbell switch (ext_enum) { 1443254885Sdumbbell case GRAPH_OBJECT_ENUM_ID1: 1444254885Sdumbbell args.v3.sExtEncoder.ucConfig |= EXTERNAL_ENCODER_CONFIG_V3_ENCODER1; 1445254885Sdumbbell break; 1446254885Sdumbbell case GRAPH_OBJECT_ENUM_ID2: 1447254885Sdumbbell args.v3.sExtEncoder.ucConfig |= EXTERNAL_ENCODER_CONFIG_V3_ENCODER2; 1448254885Sdumbbell break; 1449254885Sdumbbell case GRAPH_OBJECT_ENUM_ID3: 1450254885Sdumbbell args.v3.sExtEncoder.ucConfig |= EXTERNAL_ENCODER_CONFIG_V3_ENCODER3; 1451254885Sdumbbell break; 1452254885Sdumbbell } 1453254885Sdumbbell args.v3.sExtEncoder.ucBitPerColor = radeon_atom_get_bpc(encoder); 1454254885Sdumbbell break; 1455254885Sdumbbell default: 1456254885Sdumbbell DRM_ERROR("Unknown table version: %d, %d\n", frev, crev); 1457254885Sdumbbell return; 1458254885Sdumbbell } 1459254885Sdumbbell break; 1460254885Sdumbbell default: 1461254885Sdumbbell DRM_ERROR("Unknown table version: %d, %d\n", frev, crev); 1462254885Sdumbbell return; 1463254885Sdumbbell } 1464254885Sdumbbell atom_execute_table(rdev->mode_info.atom_context, index, (uint32_t *)&args); 1465254885Sdumbbell} 1466254885Sdumbbell 1467254885Sdumbbellstatic void 1468254885Sdumbbellatombios_yuv_setup(struct drm_encoder *encoder, bool enable) 1469254885Sdumbbell{ 1470254885Sdumbbell struct drm_device *dev = encoder->dev; 1471254885Sdumbbell struct radeon_device *rdev = dev->dev_private; 1472254885Sdumbbell struct radeon_encoder *radeon_encoder = to_radeon_encoder(encoder); 1473254885Sdumbbell struct radeon_crtc *radeon_crtc = to_radeon_crtc(encoder->crtc); 1474254885Sdumbbell ENABLE_YUV_PS_ALLOCATION args; 1475254885Sdumbbell int index = GetIndexIntoMasterTable(COMMAND, EnableYUV); 1476254885Sdumbbell uint32_t temp, reg; 1477254885Sdumbbell 1478254885Sdumbbell memset(&args, 0, sizeof(args)); 1479254885Sdumbbell 1480254885Sdumbbell if (rdev->family >= CHIP_R600) 1481254885Sdumbbell reg = R600_BIOS_3_SCRATCH; 1482254885Sdumbbell else 1483254885Sdumbbell reg = RADEON_BIOS_3_SCRATCH; 1484254885Sdumbbell 1485254885Sdumbbell /* XXX: fix up scratch reg handling */ 1486254885Sdumbbell temp = RREG32(reg); 1487254885Sdumbbell if (radeon_encoder->active_device & (ATOM_DEVICE_TV_SUPPORT)) 1488254885Sdumbbell WREG32(reg, (ATOM_S3_TV1_ACTIVE | 1489254885Sdumbbell (radeon_crtc->crtc_id << 18))); 1490254885Sdumbbell else if (radeon_encoder->active_device & (ATOM_DEVICE_CV_SUPPORT)) 1491254885Sdumbbell WREG32(reg, (ATOM_S3_CV_ACTIVE | (radeon_crtc->crtc_id << 24))); 1492254885Sdumbbell else 1493254885Sdumbbell WREG32(reg, 0); 1494254885Sdumbbell 1495254885Sdumbbell if (enable) 1496254885Sdumbbell args.ucEnable = ATOM_ENABLE; 1497254885Sdumbbell args.ucCRTC = radeon_crtc->crtc_id; 1498254885Sdumbbell 1499254885Sdumbbell atom_execute_table(rdev->mode_info.atom_context, index, (uint32_t *)&args); 1500254885Sdumbbell 1501254885Sdumbbell WREG32(reg, temp); 1502254885Sdumbbell} 1503254885Sdumbbell 1504254885Sdumbbellstatic void 1505254885Sdumbbellradeon_atom_encoder_dpms_avivo(struct drm_encoder *encoder, int mode) 1506254885Sdumbbell{ 1507254885Sdumbbell struct drm_device *dev = encoder->dev; 1508254885Sdumbbell struct radeon_device *rdev = dev->dev_private; 1509254885Sdumbbell struct radeon_encoder *radeon_encoder = to_radeon_encoder(encoder); 1510254885Sdumbbell DISPLAY_DEVICE_OUTPUT_CONTROL_PS_ALLOCATION args; 1511254885Sdumbbell int index = 0; 1512254885Sdumbbell 1513254885Sdumbbell memset(&args, 0, sizeof(args)); 1514254885Sdumbbell 1515254885Sdumbbell switch (radeon_encoder->encoder_id) { 1516254885Sdumbbell case ENCODER_OBJECT_ID_INTERNAL_TMDS1: 1517254885Sdumbbell case ENCODER_OBJECT_ID_INTERNAL_KLDSCP_TMDS1: 1518254885Sdumbbell index = GetIndexIntoMasterTable(COMMAND, TMDSAOutputControl); 1519254885Sdumbbell break; 1520254885Sdumbbell case ENCODER_OBJECT_ID_INTERNAL_DVO1: 1521254885Sdumbbell case ENCODER_OBJECT_ID_INTERNAL_DDI: 1522254885Sdumbbell case ENCODER_OBJECT_ID_INTERNAL_KLDSCP_DVO1: 1523254885Sdumbbell index = GetIndexIntoMasterTable(COMMAND, DVOOutputControl); 1524254885Sdumbbell break; 1525254885Sdumbbell case ENCODER_OBJECT_ID_INTERNAL_LVDS: 1526254885Sdumbbell index = GetIndexIntoMasterTable(COMMAND, LCD1OutputControl); 1527254885Sdumbbell break; 1528254885Sdumbbell case ENCODER_OBJECT_ID_INTERNAL_LVTM1: 1529254885Sdumbbell if (radeon_encoder->devices & (ATOM_DEVICE_LCD_SUPPORT)) 1530254885Sdumbbell index = GetIndexIntoMasterTable(COMMAND, LCD1OutputControl); 1531254885Sdumbbell else 1532254885Sdumbbell index = GetIndexIntoMasterTable(COMMAND, LVTMAOutputControl); 1533254885Sdumbbell break; 1534254885Sdumbbell case ENCODER_OBJECT_ID_INTERNAL_DAC1: 1535254885Sdumbbell case ENCODER_OBJECT_ID_INTERNAL_KLDSCP_DAC1: 1536254885Sdumbbell if (radeon_encoder->active_device & (ATOM_DEVICE_TV_SUPPORT)) 1537254885Sdumbbell index = GetIndexIntoMasterTable(COMMAND, TV1OutputControl); 1538254885Sdumbbell else if (radeon_encoder->active_device & (ATOM_DEVICE_CV_SUPPORT)) 1539254885Sdumbbell index = GetIndexIntoMasterTable(COMMAND, CV1OutputControl); 1540254885Sdumbbell else 1541254885Sdumbbell index = GetIndexIntoMasterTable(COMMAND, DAC1OutputControl); 1542254885Sdumbbell break; 1543254885Sdumbbell case ENCODER_OBJECT_ID_INTERNAL_DAC2: 1544254885Sdumbbell case ENCODER_OBJECT_ID_INTERNAL_KLDSCP_DAC2: 1545254885Sdumbbell if (radeon_encoder->active_device & (ATOM_DEVICE_TV_SUPPORT)) 1546254885Sdumbbell index = GetIndexIntoMasterTable(COMMAND, TV1OutputControl); 1547254885Sdumbbell else if (radeon_encoder->active_device & (ATOM_DEVICE_CV_SUPPORT)) 1548254885Sdumbbell index = GetIndexIntoMasterTable(COMMAND, CV1OutputControl); 1549254885Sdumbbell else 1550254885Sdumbbell index = GetIndexIntoMasterTable(COMMAND, DAC2OutputControl); 1551254885Sdumbbell break; 1552254885Sdumbbell default: 1553254885Sdumbbell return; 1554254885Sdumbbell } 1555254885Sdumbbell 1556254885Sdumbbell switch (mode) { 1557254885Sdumbbell case DRM_MODE_DPMS_ON: 1558254885Sdumbbell args.ucAction = ATOM_ENABLE; 1559254885Sdumbbell /* workaround for DVOOutputControl on some RS690 systems */ 1560254885Sdumbbell if (radeon_encoder->encoder_id == ENCODER_OBJECT_ID_INTERNAL_DDI) { 1561254885Sdumbbell u32 reg = RREG32(RADEON_BIOS_3_SCRATCH); 1562254885Sdumbbell WREG32(RADEON_BIOS_3_SCRATCH, reg & ~ATOM_S3_DFP2I_ACTIVE); 1563254885Sdumbbell atom_execute_table(rdev->mode_info.atom_context, index, (uint32_t *)&args); 1564254885Sdumbbell WREG32(RADEON_BIOS_3_SCRATCH, reg); 1565254885Sdumbbell } else 1566254885Sdumbbell atom_execute_table(rdev->mode_info.atom_context, index, (uint32_t *)&args); 1567254885Sdumbbell if (radeon_encoder->devices & (ATOM_DEVICE_LCD_SUPPORT)) { 1568254885Sdumbbell args.ucAction = ATOM_LCD_BLON; 1569254885Sdumbbell atom_execute_table(rdev->mode_info.atom_context, index, (uint32_t *)&args); 1570254885Sdumbbell } 1571254885Sdumbbell break; 1572254885Sdumbbell case DRM_MODE_DPMS_STANDBY: 1573254885Sdumbbell case DRM_MODE_DPMS_SUSPEND: 1574254885Sdumbbell case DRM_MODE_DPMS_OFF: 1575254885Sdumbbell args.ucAction = ATOM_DISABLE; 1576254885Sdumbbell atom_execute_table(rdev->mode_info.atom_context, index, (uint32_t *)&args); 1577254885Sdumbbell if (radeon_encoder->devices & (ATOM_DEVICE_LCD_SUPPORT)) { 1578254885Sdumbbell args.ucAction = ATOM_LCD_BLOFF; 1579254885Sdumbbell atom_execute_table(rdev->mode_info.atom_context, index, (uint32_t *)&args); 1580254885Sdumbbell } 1581254885Sdumbbell break; 1582254885Sdumbbell } 1583254885Sdumbbell} 1584254885Sdumbbell 1585254885Sdumbbellstatic void 1586254885Sdumbbellradeon_atom_encoder_dpms_dig(struct drm_encoder *encoder, int mode) 1587254885Sdumbbell{ 1588254885Sdumbbell struct drm_device *dev = encoder->dev; 1589254885Sdumbbell struct radeon_device *rdev = dev->dev_private; 1590254885Sdumbbell struct radeon_encoder *radeon_encoder = to_radeon_encoder(encoder); 1591254885Sdumbbell struct drm_encoder *ext_encoder = radeon_get_external_encoder(encoder); 1592254885Sdumbbell struct radeon_encoder_atom_dig *dig = radeon_encoder->enc_priv; 1593254885Sdumbbell struct drm_connector *connector = radeon_get_connector_for_encoder(encoder); 1594254885Sdumbbell struct radeon_connector *radeon_connector = NULL; 1595254885Sdumbbell struct radeon_connector_atom_dig *radeon_dig_connector = NULL; 1596254885Sdumbbell 1597254885Sdumbbell if (connector) { 1598254885Sdumbbell radeon_connector = to_radeon_connector(connector); 1599254885Sdumbbell radeon_dig_connector = radeon_connector->con_priv; 1600254885Sdumbbell } 1601254885Sdumbbell 1602254885Sdumbbell switch (mode) { 1603254885Sdumbbell case DRM_MODE_DPMS_ON: 1604254885Sdumbbell if (ASIC_IS_DCE41(rdev) || ASIC_IS_DCE5(rdev)) { 1605254885Sdumbbell if (!connector) 1606254885Sdumbbell dig->panel_mode = DP_PANEL_MODE_EXTERNAL_DP_MODE; 1607254885Sdumbbell else 1608254885Sdumbbell dig->panel_mode = radeon_dp_get_panel_mode(encoder, connector); 1609254885Sdumbbell 1610254885Sdumbbell /* setup and enable the encoder */ 1611254885Sdumbbell atombios_dig_encoder_setup(encoder, ATOM_ENCODER_CMD_SETUP, 0); 1612254885Sdumbbell atombios_dig_encoder_setup(encoder, 1613254885Sdumbbell ATOM_ENCODER_CMD_SETUP_PANEL_MODE, 1614254885Sdumbbell dig->panel_mode); 1615254885Sdumbbell if (ext_encoder) { 1616254885Sdumbbell if (ASIC_IS_DCE41(rdev) || ASIC_IS_DCE61(rdev)) 1617254885Sdumbbell atombios_external_encoder_setup(encoder, ext_encoder, 1618254885Sdumbbell EXTERNAL_ENCODER_ACTION_V3_ENCODER_SETUP); 1619254885Sdumbbell } 1620254885Sdumbbell atombios_dig_transmitter_setup(encoder, ATOM_TRANSMITTER_ACTION_ENABLE, 0, 0); 1621254885Sdumbbell } else if (ASIC_IS_DCE4(rdev)) { 1622254885Sdumbbell /* setup and enable the encoder */ 1623254885Sdumbbell atombios_dig_encoder_setup(encoder, ATOM_ENCODER_CMD_SETUP, 0); 1624254885Sdumbbell /* enable the transmitter */ 1625254885Sdumbbell atombios_dig_transmitter_setup(encoder, ATOM_TRANSMITTER_ACTION_ENABLE, 0, 0); 1626254885Sdumbbell atombios_dig_transmitter_setup(encoder, ATOM_TRANSMITTER_ACTION_ENABLE_OUTPUT, 0, 0); 1627254885Sdumbbell } else { 1628254885Sdumbbell /* setup and enable the encoder and transmitter */ 1629254885Sdumbbell atombios_dig_encoder_setup(encoder, ATOM_ENABLE, 0); 1630254885Sdumbbell atombios_dig_transmitter_setup(encoder, ATOM_TRANSMITTER_ACTION_SETUP, 0, 0); 1631254885Sdumbbell atombios_dig_transmitter_setup(encoder, ATOM_TRANSMITTER_ACTION_ENABLE, 0, 0); 1632254885Sdumbbell /* some early dce3.2 boards have a bug in their transmitter control table */ 1633254885Sdumbbell if ((rdev->family != CHIP_RV710) && (rdev->family != CHIP_RV730)) 1634254885Sdumbbell atombios_dig_transmitter_setup(encoder, ATOM_TRANSMITTER_ACTION_ENABLE_OUTPUT, 0, 0); 1635254885Sdumbbell } 1636254885Sdumbbell if (ENCODER_MODE_IS_DP(atombios_get_encoder_mode(encoder)) && connector) { 1637254885Sdumbbell if (connector->connector_type == DRM_MODE_CONNECTOR_eDP) { 1638254885Sdumbbell atombios_set_edp_panel_power(connector, 1639254885Sdumbbell ATOM_TRANSMITTER_ACTION_POWER_ON); 1640254885Sdumbbell radeon_dig_connector->edp_on = true; 1641254885Sdumbbell } 1642254885Sdumbbell radeon_dp_link_train(encoder, connector); 1643254885Sdumbbell if (ASIC_IS_DCE4(rdev)) 1644254885Sdumbbell atombios_dig_encoder_setup(encoder, ATOM_ENCODER_CMD_DP_VIDEO_ON, 0); 1645254885Sdumbbell } 1646254885Sdumbbell if (radeon_encoder->devices & (ATOM_DEVICE_LCD_SUPPORT)) 1647254885Sdumbbell atombios_dig_transmitter_setup(encoder, ATOM_TRANSMITTER_ACTION_LCD_BLON, 0, 0); 1648254885Sdumbbell break; 1649254885Sdumbbell case DRM_MODE_DPMS_STANDBY: 1650254885Sdumbbell case DRM_MODE_DPMS_SUSPEND: 1651254885Sdumbbell case DRM_MODE_DPMS_OFF: 1652254885Sdumbbell if (ASIC_IS_DCE41(rdev) || ASIC_IS_DCE5(rdev)) { 1653254885Sdumbbell /* disable the transmitter */ 1654254885Sdumbbell atombios_dig_transmitter_setup(encoder, ATOM_TRANSMITTER_ACTION_DISABLE, 0, 0); 1655254885Sdumbbell } else if (ASIC_IS_DCE4(rdev)) { 1656254885Sdumbbell /* disable the transmitter */ 1657254885Sdumbbell atombios_dig_transmitter_setup(encoder, ATOM_TRANSMITTER_ACTION_DISABLE_OUTPUT, 0, 0); 1658254885Sdumbbell atombios_dig_transmitter_setup(encoder, ATOM_TRANSMITTER_ACTION_DISABLE, 0, 0); 1659254885Sdumbbell } else { 1660254885Sdumbbell /* disable the encoder and transmitter */ 1661254885Sdumbbell atombios_dig_transmitter_setup(encoder, ATOM_TRANSMITTER_ACTION_DISABLE_OUTPUT, 0, 0); 1662254885Sdumbbell atombios_dig_transmitter_setup(encoder, ATOM_TRANSMITTER_ACTION_DISABLE, 0, 0); 1663254885Sdumbbell atombios_dig_encoder_setup(encoder, ATOM_DISABLE, 0); 1664254885Sdumbbell } 1665254885Sdumbbell if (ENCODER_MODE_IS_DP(atombios_get_encoder_mode(encoder)) && connector) { 1666254885Sdumbbell if (ASIC_IS_DCE4(rdev)) 1667254885Sdumbbell atombios_dig_encoder_setup(encoder, ATOM_ENCODER_CMD_DP_VIDEO_OFF, 0); 1668254885Sdumbbell if (connector->connector_type == DRM_MODE_CONNECTOR_eDP) { 1669254885Sdumbbell atombios_set_edp_panel_power(connector, 1670254885Sdumbbell ATOM_TRANSMITTER_ACTION_POWER_OFF); 1671254885Sdumbbell radeon_dig_connector->edp_on = false; 1672254885Sdumbbell } 1673254885Sdumbbell } 1674254885Sdumbbell if (radeon_encoder->devices & (ATOM_DEVICE_LCD_SUPPORT)) 1675254885Sdumbbell atombios_dig_transmitter_setup(encoder, ATOM_TRANSMITTER_ACTION_LCD_BLOFF, 0, 0); 1676254885Sdumbbell break; 1677254885Sdumbbell } 1678254885Sdumbbell} 1679254885Sdumbbell 1680254885Sdumbbellstatic void 1681254885Sdumbbellradeon_atom_encoder_dpms_ext(struct drm_encoder *encoder, 1682254885Sdumbbell struct drm_encoder *ext_encoder, 1683254885Sdumbbell int mode) 1684254885Sdumbbell{ 1685254885Sdumbbell struct drm_device *dev = encoder->dev; 1686254885Sdumbbell struct radeon_device *rdev = dev->dev_private; 1687254885Sdumbbell 1688254885Sdumbbell switch (mode) { 1689254885Sdumbbell case DRM_MODE_DPMS_ON: 1690254885Sdumbbell default: 1691254885Sdumbbell if (ASIC_IS_DCE41(rdev) || ASIC_IS_DCE61(rdev)) { 1692254885Sdumbbell atombios_external_encoder_setup(encoder, ext_encoder, 1693254885Sdumbbell EXTERNAL_ENCODER_ACTION_V3_ENABLE_OUTPUT); 1694254885Sdumbbell atombios_external_encoder_setup(encoder, ext_encoder, 1695254885Sdumbbell EXTERNAL_ENCODER_ACTION_V3_ENCODER_BLANKING_OFF); 1696254885Sdumbbell } else 1697254885Sdumbbell atombios_external_encoder_setup(encoder, ext_encoder, ATOM_ENABLE); 1698254885Sdumbbell break; 1699254885Sdumbbell case DRM_MODE_DPMS_STANDBY: 1700254885Sdumbbell case DRM_MODE_DPMS_SUSPEND: 1701254885Sdumbbell case DRM_MODE_DPMS_OFF: 1702254885Sdumbbell if (ASIC_IS_DCE41(rdev) || ASIC_IS_DCE61(rdev)) { 1703254885Sdumbbell atombios_external_encoder_setup(encoder, ext_encoder, 1704254885Sdumbbell EXTERNAL_ENCODER_ACTION_V3_ENCODER_BLANKING); 1705254885Sdumbbell atombios_external_encoder_setup(encoder, ext_encoder, 1706254885Sdumbbell EXTERNAL_ENCODER_ACTION_V3_DISABLE_OUTPUT); 1707254885Sdumbbell } else 1708254885Sdumbbell atombios_external_encoder_setup(encoder, ext_encoder, ATOM_DISABLE); 1709254885Sdumbbell break; 1710254885Sdumbbell } 1711254885Sdumbbell} 1712254885Sdumbbell 1713254885Sdumbbellstatic void 1714254885Sdumbbellradeon_atom_encoder_dpms(struct drm_encoder *encoder, int mode) 1715254885Sdumbbell{ 1716254885Sdumbbell struct drm_device *dev = encoder->dev; 1717254885Sdumbbell struct radeon_device *rdev = dev->dev_private; 1718254885Sdumbbell struct radeon_encoder *radeon_encoder = to_radeon_encoder(encoder); 1719254885Sdumbbell struct drm_encoder *ext_encoder = radeon_get_external_encoder(encoder); 1720254885Sdumbbell 1721254885Sdumbbell DRM_DEBUG_KMS("encoder dpms %d to mode %d, devices %08x, active_devices %08x\n", 1722254885Sdumbbell radeon_encoder->encoder_id, mode, radeon_encoder->devices, 1723254885Sdumbbell radeon_encoder->active_device); 1724254885Sdumbbell switch (radeon_encoder->encoder_id) { 1725254885Sdumbbell case ENCODER_OBJECT_ID_INTERNAL_TMDS1: 1726254885Sdumbbell case ENCODER_OBJECT_ID_INTERNAL_KLDSCP_TMDS1: 1727254885Sdumbbell case ENCODER_OBJECT_ID_INTERNAL_LVDS: 1728254885Sdumbbell case ENCODER_OBJECT_ID_INTERNAL_LVTM1: 1729254885Sdumbbell case ENCODER_OBJECT_ID_INTERNAL_DVO1: 1730254885Sdumbbell case ENCODER_OBJECT_ID_INTERNAL_DDI: 1731254885Sdumbbell case ENCODER_OBJECT_ID_INTERNAL_DAC2: 1732254885Sdumbbell case ENCODER_OBJECT_ID_INTERNAL_KLDSCP_DAC2: 1733254885Sdumbbell radeon_atom_encoder_dpms_avivo(encoder, mode); 1734254885Sdumbbell break; 1735254885Sdumbbell case ENCODER_OBJECT_ID_INTERNAL_UNIPHY: 1736254885Sdumbbell case ENCODER_OBJECT_ID_INTERNAL_UNIPHY1: 1737254885Sdumbbell case ENCODER_OBJECT_ID_INTERNAL_UNIPHY2: 1738254885Sdumbbell case ENCODER_OBJECT_ID_INTERNAL_KLDSCP_LVTMA: 1739254885Sdumbbell radeon_atom_encoder_dpms_dig(encoder, mode); 1740254885Sdumbbell break; 1741254885Sdumbbell case ENCODER_OBJECT_ID_INTERNAL_KLDSCP_DVO1: 1742254885Sdumbbell if (ASIC_IS_DCE5(rdev)) { 1743254885Sdumbbell switch (mode) { 1744254885Sdumbbell case DRM_MODE_DPMS_ON: 1745254885Sdumbbell atombios_dvo_setup(encoder, ATOM_ENABLE); 1746254885Sdumbbell break; 1747254885Sdumbbell case DRM_MODE_DPMS_STANDBY: 1748254885Sdumbbell case DRM_MODE_DPMS_SUSPEND: 1749254885Sdumbbell case DRM_MODE_DPMS_OFF: 1750254885Sdumbbell atombios_dvo_setup(encoder, ATOM_DISABLE); 1751254885Sdumbbell break; 1752254885Sdumbbell } 1753254885Sdumbbell } else if (ASIC_IS_DCE3(rdev)) 1754254885Sdumbbell radeon_atom_encoder_dpms_dig(encoder, mode); 1755254885Sdumbbell else 1756254885Sdumbbell radeon_atom_encoder_dpms_avivo(encoder, mode); 1757254885Sdumbbell break; 1758254885Sdumbbell case ENCODER_OBJECT_ID_INTERNAL_DAC1: 1759254885Sdumbbell case ENCODER_OBJECT_ID_INTERNAL_KLDSCP_DAC1: 1760254885Sdumbbell if (ASIC_IS_DCE5(rdev)) { 1761254885Sdumbbell switch (mode) { 1762254885Sdumbbell case DRM_MODE_DPMS_ON: 1763254885Sdumbbell atombios_dac_setup(encoder, ATOM_ENABLE); 1764254885Sdumbbell break; 1765254885Sdumbbell case DRM_MODE_DPMS_STANDBY: 1766254885Sdumbbell case DRM_MODE_DPMS_SUSPEND: 1767254885Sdumbbell case DRM_MODE_DPMS_OFF: 1768254885Sdumbbell atombios_dac_setup(encoder, ATOM_DISABLE); 1769254885Sdumbbell break; 1770254885Sdumbbell } 1771254885Sdumbbell } else 1772254885Sdumbbell radeon_atom_encoder_dpms_avivo(encoder, mode); 1773254885Sdumbbell break; 1774254885Sdumbbell default: 1775254885Sdumbbell return; 1776254885Sdumbbell } 1777254885Sdumbbell 1778254885Sdumbbell if (ext_encoder) 1779254885Sdumbbell radeon_atom_encoder_dpms_ext(encoder, ext_encoder, mode); 1780254885Sdumbbell 1781254885Sdumbbell radeon_atombios_encoder_dpms_scratch_regs(encoder, (mode == DRM_MODE_DPMS_ON) ? true : false); 1782254885Sdumbbell 1783254885Sdumbbell} 1784254885Sdumbbell 1785254885Sdumbbellunion crtc_source_param { 1786254885Sdumbbell SELECT_CRTC_SOURCE_PS_ALLOCATION v1; 1787254885Sdumbbell SELECT_CRTC_SOURCE_PARAMETERS_V2 v2; 1788254885Sdumbbell}; 1789254885Sdumbbell 1790254885Sdumbbellstatic void 1791254885Sdumbbellatombios_set_encoder_crtc_source(struct drm_encoder *encoder) 1792254885Sdumbbell{ 1793254885Sdumbbell struct drm_device *dev = encoder->dev; 1794254885Sdumbbell struct radeon_device *rdev = dev->dev_private; 1795254885Sdumbbell struct radeon_encoder *radeon_encoder = to_radeon_encoder(encoder); 1796254885Sdumbbell struct radeon_crtc *radeon_crtc = to_radeon_crtc(encoder->crtc); 1797254885Sdumbbell union crtc_source_param args; 1798254885Sdumbbell int index = GetIndexIntoMasterTable(COMMAND, SelectCRTC_Source); 1799254885Sdumbbell uint8_t frev, crev; 1800254885Sdumbbell struct radeon_encoder_atom_dig *dig; 1801254885Sdumbbell 1802254885Sdumbbell memset(&args, 0, sizeof(args)); 1803254885Sdumbbell 1804254885Sdumbbell if (!atom_parse_cmd_header(rdev->mode_info.atom_context, index, &frev, &crev)) 1805254885Sdumbbell return; 1806254885Sdumbbell 1807254885Sdumbbell switch (frev) { 1808254885Sdumbbell case 1: 1809254885Sdumbbell switch (crev) { 1810254885Sdumbbell case 1: 1811254885Sdumbbell default: 1812254885Sdumbbell if (ASIC_IS_AVIVO(rdev)) 1813254885Sdumbbell args.v1.ucCRTC = radeon_crtc->crtc_id; 1814254885Sdumbbell else { 1815254885Sdumbbell if (radeon_encoder->encoder_id == ENCODER_OBJECT_ID_INTERNAL_DAC1) { 1816254885Sdumbbell args.v1.ucCRTC = radeon_crtc->crtc_id; 1817254885Sdumbbell } else { 1818254885Sdumbbell args.v1.ucCRTC = radeon_crtc->crtc_id << 2; 1819254885Sdumbbell } 1820254885Sdumbbell } 1821254885Sdumbbell switch (radeon_encoder->encoder_id) { 1822254885Sdumbbell case ENCODER_OBJECT_ID_INTERNAL_TMDS1: 1823254885Sdumbbell case ENCODER_OBJECT_ID_INTERNAL_KLDSCP_TMDS1: 1824254885Sdumbbell args.v1.ucDevice = ATOM_DEVICE_DFP1_INDEX; 1825254885Sdumbbell break; 1826254885Sdumbbell case ENCODER_OBJECT_ID_INTERNAL_LVDS: 1827254885Sdumbbell case ENCODER_OBJECT_ID_INTERNAL_LVTM1: 1828254885Sdumbbell if (radeon_encoder->devices & ATOM_DEVICE_LCD1_SUPPORT) 1829254885Sdumbbell args.v1.ucDevice = ATOM_DEVICE_LCD1_INDEX; 1830254885Sdumbbell else 1831254885Sdumbbell args.v1.ucDevice = ATOM_DEVICE_DFP3_INDEX; 1832254885Sdumbbell break; 1833254885Sdumbbell case ENCODER_OBJECT_ID_INTERNAL_DVO1: 1834254885Sdumbbell case ENCODER_OBJECT_ID_INTERNAL_DDI: 1835254885Sdumbbell case ENCODER_OBJECT_ID_INTERNAL_KLDSCP_DVO1: 1836254885Sdumbbell args.v1.ucDevice = ATOM_DEVICE_DFP2_INDEX; 1837254885Sdumbbell break; 1838254885Sdumbbell case ENCODER_OBJECT_ID_INTERNAL_DAC1: 1839254885Sdumbbell case ENCODER_OBJECT_ID_INTERNAL_KLDSCP_DAC1: 1840254885Sdumbbell if (radeon_encoder->active_device & (ATOM_DEVICE_TV_SUPPORT)) 1841254885Sdumbbell args.v1.ucDevice = ATOM_DEVICE_TV1_INDEX; 1842254885Sdumbbell else if (radeon_encoder->active_device & (ATOM_DEVICE_CV_SUPPORT)) 1843254885Sdumbbell args.v1.ucDevice = ATOM_DEVICE_CV_INDEX; 1844254885Sdumbbell else 1845254885Sdumbbell args.v1.ucDevice = ATOM_DEVICE_CRT1_INDEX; 1846254885Sdumbbell break; 1847254885Sdumbbell case ENCODER_OBJECT_ID_INTERNAL_DAC2: 1848254885Sdumbbell case ENCODER_OBJECT_ID_INTERNAL_KLDSCP_DAC2: 1849254885Sdumbbell if (radeon_encoder->active_device & (ATOM_DEVICE_TV_SUPPORT)) 1850254885Sdumbbell args.v1.ucDevice = ATOM_DEVICE_TV1_INDEX; 1851254885Sdumbbell else if (radeon_encoder->active_device & (ATOM_DEVICE_CV_SUPPORT)) 1852254885Sdumbbell args.v1.ucDevice = ATOM_DEVICE_CV_INDEX; 1853254885Sdumbbell else 1854254885Sdumbbell args.v1.ucDevice = ATOM_DEVICE_CRT2_INDEX; 1855254885Sdumbbell break; 1856254885Sdumbbell } 1857254885Sdumbbell break; 1858254885Sdumbbell case 2: 1859254885Sdumbbell args.v2.ucCRTC = radeon_crtc->crtc_id; 1860254885Sdumbbell if (radeon_encoder_get_dp_bridge_encoder_id(encoder) != ENCODER_OBJECT_ID_NONE) { 1861254885Sdumbbell struct drm_connector *connector = radeon_get_connector_for_encoder(encoder); 1862254885Sdumbbell 1863254885Sdumbbell if (connector->connector_type == DRM_MODE_CONNECTOR_LVDS) 1864254885Sdumbbell args.v2.ucEncodeMode = ATOM_ENCODER_MODE_LVDS; 1865254885Sdumbbell else if (connector->connector_type == DRM_MODE_CONNECTOR_VGA) 1866254885Sdumbbell args.v2.ucEncodeMode = ATOM_ENCODER_MODE_CRT; 1867254885Sdumbbell else 1868254885Sdumbbell args.v2.ucEncodeMode = atombios_get_encoder_mode(encoder); 1869254885Sdumbbell } else 1870254885Sdumbbell args.v2.ucEncodeMode = atombios_get_encoder_mode(encoder); 1871254885Sdumbbell switch (radeon_encoder->encoder_id) { 1872254885Sdumbbell case ENCODER_OBJECT_ID_INTERNAL_UNIPHY: 1873254885Sdumbbell case ENCODER_OBJECT_ID_INTERNAL_UNIPHY1: 1874254885Sdumbbell case ENCODER_OBJECT_ID_INTERNAL_UNIPHY2: 1875254885Sdumbbell case ENCODER_OBJECT_ID_INTERNAL_KLDSCP_LVTMA: 1876254885Sdumbbell dig = radeon_encoder->enc_priv; 1877254885Sdumbbell switch (dig->dig_encoder) { 1878254885Sdumbbell case 0: 1879254885Sdumbbell args.v2.ucEncoderID = ASIC_INT_DIG1_ENCODER_ID; 1880254885Sdumbbell break; 1881254885Sdumbbell case 1: 1882254885Sdumbbell args.v2.ucEncoderID = ASIC_INT_DIG2_ENCODER_ID; 1883254885Sdumbbell break; 1884254885Sdumbbell case 2: 1885254885Sdumbbell args.v2.ucEncoderID = ASIC_INT_DIG3_ENCODER_ID; 1886254885Sdumbbell break; 1887254885Sdumbbell case 3: 1888254885Sdumbbell args.v2.ucEncoderID = ASIC_INT_DIG4_ENCODER_ID; 1889254885Sdumbbell break; 1890254885Sdumbbell case 4: 1891254885Sdumbbell args.v2.ucEncoderID = ASIC_INT_DIG5_ENCODER_ID; 1892254885Sdumbbell break; 1893254885Sdumbbell case 5: 1894254885Sdumbbell args.v2.ucEncoderID = ASIC_INT_DIG6_ENCODER_ID; 1895254885Sdumbbell break; 1896254885Sdumbbell } 1897254885Sdumbbell break; 1898254885Sdumbbell case ENCODER_OBJECT_ID_INTERNAL_KLDSCP_DVO1: 1899254885Sdumbbell args.v2.ucEncoderID = ASIC_INT_DVO_ENCODER_ID; 1900254885Sdumbbell break; 1901254885Sdumbbell case ENCODER_OBJECT_ID_INTERNAL_KLDSCP_DAC1: 1902254885Sdumbbell if (radeon_encoder->active_device & (ATOM_DEVICE_TV_SUPPORT)) 1903254885Sdumbbell args.v2.ucEncoderID = ASIC_INT_TV_ENCODER_ID; 1904254885Sdumbbell else if (radeon_encoder->active_device & (ATOM_DEVICE_CV_SUPPORT)) 1905254885Sdumbbell args.v2.ucEncoderID = ASIC_INT_TV_ENCODER_ID; 1906254885Sdumbbell else 1907254885Sdumbbell args.v2.ucEncoderID = ASIC_INT_DAC1_ENCODER_ID; 1908254885Sdumbbell break; 1909254885Sdumbbell case ENCODER_OBJECT_ID_INTERNAL_KLDSCP_DAC2: 1910254885Sdumbbell if (radeon_encoder->active_device & (ATOM_DEVICE_TV_SUPPORT)) 1911254885Sdumbbell args.v2.ucEncoderID = ASIC_INT_TV_ENCODER_ID; 1912254885Sdumbbell else if (radeon_encoder->active_device & (ATOM_DEVICE_CV_SUPPORT)) 1913254885Sdumbbell args.v2.ucEncoderID = ASIC_INT_TV_ENCODER_ID; 1914254885Sdumbbell else 1915254885Sdumbbell args.v2.ucEncoderID = ASIC_INT_DAC2_ENCODER_ID; 1916254885Sdumbbell break; 1917254885Sdumbbell } 1918254885Sdumbbell break; 1919254885Sdumbbell } 1920254885Sdumbbell break; 1921254885Sdumbbell default: 1922254885Sdumbbell DRM_ERROR("Unknown table version: %d, %d\n", frev, crev); 1923254885Sdumbbell return; 1924254885Sdumbbell } 1925254885Sdumbbell 1926254885Sdumbbell atom_execute_table(rdev->mode_info.atom_context, index, (uint32_t *)&args); 1927254885Sdumbbell 1928254885Sdumbbell /* update scratch regs with new routing */ 1929254885Sdumbbell radeon_atombios_encoder_crtc_scratch_regs(encoder, radeon_crtc->crtc_id); 1930254885Sdumbbell} 1931254885Sdumbbell 1932254885Sdumbbellstatic void 1933254885Sdumbbellatombios_apply_encoder_quirks(struct drm_encoder *encoder, 1934254885Sdumbbell struct drm_display_mode *mode) 1935254885Sdumbbell{ 1936254885Sdumbbell struct drm_device *dev = encoder->dev; 1937254885Sdumbbell struct radeon_device *rdev = dev->dev_private; 1938254885Sdumbbell struct radeon_encoder *radeon_encoder = to_radeon_encoder(encoder); 1939254885Sdumbbell struct radeon_crtc *radeon_crtc = to_radeon_crtc(encoder->crtc); 1940254885Sdumbbell 1941254885Sdumbbell /* Funky macbooks */ 1942254885Sdumbbell if ((dev->pci_device == 0x71C5) && 1943254885Sdumbbell (dev->pci_subvendor == 0x106b) && 1944254885Sdumbbell (dev->pci_subdevice == 0x0080)) { 1945254885Sdumbbell if (radeon_encoder->devices & ATOM_DEVICE_LCD1_SUPPORT) { 1946254885Sdumbbell uint32_t lvtma_bit_depth_control = RREG32(AVIVO_LVTMA_BIT_DEPTH_CONTROL); 1947254885Sdumbbell 1948254885Sdumbbell lvtma_bit_depth_control &= ~AVIVO_LVTMA_BIT_DEPTH_CONTROL_TRUNCATE_EN; 1949254885Sdumbbell lvtma_bit_depth_control &= ~AVIVO_LVTMA_BIT_DEPTH_CONTROL_SPATIAL_DITHER_EN; 1950254885Sdumbbell 1951254885Sdumbbell WREG32(AVIVO_LVTMA_BIT_DEPTH_CONTROL, lvtma_bit_depth_control); 1952254885Sdumbbell } 1953254885Sdumbbell } 1954254885Sdumbbell 1955254885Sdumbbell /* set scaler clears this on some chips */ 1956254885Sdumbbell if (ASIC_IS_AVIVO(rdev) && 1957254885Sdumbbell (!(radeon_encoder->active_device & (ATOM_DEVICE_TV_SUPPORT)))) { 1958254885Sdumbbell if (ASIC_IS_DCE4(rdev)) { 1959254885Sdumbbell if (mode->flags & DRM_MODE_FLAG_INTERLACE) 1960254885Sdumbbell WREG32(EVERGREEN_DATA_FORMAT + radeon_crtc->crtc_offset, 1961254885Sdumbbell EVERGREEN_INTERLEAVE_EN); 1962254885Sdumbbell else 1963254885Sdumbbell WREG32(EVERGREEN_DATA_FORMAT + radeon_crtc->crtc_offset, 0); 1964254885Sdumbbell } else { 1965254885Sdumbbell if (mode->flags & DRM_MODE_FLAG_INTERLACE) 1966254885Sdumbbell WREG32(AVIVO_D1MODE_DATA_FORMAT + radeon_crtc->crtc_offset, 1967254885Sdumbbell AVIVO_D1MODE_INTERLEAVE_EN); 1968254885Sdumbbell else 1969254885Sdumbbell WREG32(AVIVO_D1MODE_DATA_FORMAT + radeon_crtc->crtc_offset, 0); 1970254885Sdumbbell } 1971254885Sdumbbell } 1972254885Sdumbbell} 1973254885Sdumbbell 1974254885Sdumbbellstatic int radeon_atom_pick_dig_encoder(struct drm_encoder *encoder) 1975254885Sdumbbell{ 1976254885Sdumbbell struct drm_device *dev = encoder->dev; 1977254885Sdumbbell struct radeon_device *rdev = dev->dev_private; 1978254885Sdumbbell struct radeon_crtc *radeon_crtc = to_radeon_crtc(encoder->crtc); 1979254885Sdumbbell struct radeon_encoder *radeon_encoder = to_radeon_encoder(encoder); 1980254885Sdumbbell struct drm_encoder *test_encoder; 1981254885Sdumbbell struct radeon_encoder_atom_dig *dig = radeon_encoder->enc_priv; 1982254885Sdumbbell uint32_t dig_enc_in_use = 0; 1983254885Sdumbbell 1984254885Sdumbbell if (ASIC_IS_DCE6(rdev)) { 1985254885Sdumbbell /* DCE6 */ 1986254885Sdumbbell switch (radeon_encoder->encoder_id) { 1987254885Sdumbbell case ENCODER_OBJECT_ID_INTERNAL_UNIPHY: 1988254885Sdumbbell if (dig->linkb) 1989254885Sdumbbell return 1; 1990254885Sdumbbell else 1991254885Sdumbbell return 0; 1992254885Sdumbbell break; 1993254885Sdumbbell case ENCODER_OBJECT_ID_INTERNAL_UNIPHY1: 1994254885Sdumbbell if (dig->linkb) 1995254885Sdumbbell return 3; 1996254885Sdumbbell else 1997254885Sdumbbell return 2; 1998254885Sdumbbell break; 1999254885Sdumbbell case ENCODER_OBJECT_ID_INTERNAL_UNIPHY2: 2000254885Sdumbbell if (dig->linkb) 2001254885Sdumbbell return 5; 2002254885Sdumbbell else 2003254885Sdumbbell return 4; 2004254885Sdumbbell break; 2005254885Sdumbbell } 2006254885Sdumbbell } else if (ASIC_IS_DCE4(rdev)) { 2007254885Sdumbbell /* DCE4/5 */ 2008254885Sdumbbell if (ASIC_IS_DCE41(rdev) && !ASIC_IS_DCE61(rdev)) { 2009254885Sdumbbell /* ontario follows DCE4 */ 2010254885Sdumbbell if (rdev->family == CHIP_PALM) { 2011254885Sdumbbell if (dig->linkb) 2012254885Sdumbbell return 1; 2013254885Sdumbbell else 2014254885Sdumbbell return 0; 2015254885Sdumbbell } else 2016254885Sdumbbell /* llano follows DCE3.2 */ 2017254885Sdumbbell return radeon_crtc->crtc_id; 2018254885Sdumbbell } else { 2019254885Sdumbbell switch (radeon_encoder->encoder_id) { 2020254885Sdumbbell case ENCODER_OBJECT_ID_INTERNAL_UNIPHY: 2021254885Sdumbbell if (dig->linkb) 2022254885Sdumbbell return 1; 2023254885Sdumbbell else 2024254885Sdumbbell return 0; 2025254885Sdumbbell break; 2026254885Sdumbbell case ENCODER_OBJECT_ID_INTERNAL_UNIPHY1: 2027254885Sdumbbell if (dig->linkb) 2028254885Sdumbbell return 3; 2029254885Sdumbbell else 2030254885Sdumbbell return 2; 2031254885Sdumbbell break; 2032254885Sdumbbell case ENCODER_OBJECT_ID_INTERNAL_UNIPHY2: 2033254885Sdumbbell if (dig->linkb) 2034254885Sdumbbell return 5; 2035254885Sdumbbell else 2036254885Sdumbbell return 4; 2037254885Sdumbbell break; 2038254885Sdumbbell } 2039254885Sdumbbell } 2040254885Sdumbbell } 2041254885Sdumbbell 2042254885Sdumbbell /* on DCE32 and encoder can driver any block so just crtc id */ 2043254885Sdumbbell if (ASIC_IS_DCE32(rdev)) { 2044254885Sdumbbell return radeon_crtc->crtc_id; 2045254885Sdumbbell } 2046254885Sdumbbell 2047254885Sdumbbell /* on DCE3 - LVTMA can only be driven by DIGB */ 2048254885Sdumbbell list_for_each_entry(test_encoder, &dev->mode_config.encoder_list, head) { 2049254885Sdumbbell struct radeon_encoder *radeon_test_encoder; 2050254885Sdumbbell 2051254885Sdumbbell if (encoder == test_encoder) 2052254885Sdumbbell continue; 2053254885Sdumbbell 2054254885Sdumbbell if (!radeon_encoder_is_digital(test_encoder)) 2055254885Sdumbbell continue; 2056254885Sdumbbell 2057254885Sdumbbell radeon_test_encoder = to_radeon_encoder(test_encoder); 2058254885Sdumbbell dig = radeon_test_encoder->enc_priv; 2059254885Sdumbbell 2060254885Sdumbbell if (dig->dig_encoder >= 0) 2061254885Sdumbbell dig_enc_in_use |= (1 << dig->dig_encoder); 2062254885Sdumbbell } 2063254885Sdumbbell 2064254885Sdumbbell if (radeon_encoder->encoder_id == ENCODER_OBJECT_ID_INTERNAL_KLDSCP_LVTMA) { 2065254885Sdumbbell if (dig_enc_in_use & 0x2) 2066254885Sdumbbell DRM_ERROR("LVDS required digital encoder 2 but it was in use - stealing\n"); 2067254885Sdumbbell return 1; 2068254885Sdumbbell } 2069254885Sdumbbell if (!(dig_enc_in_use & 1)) 2070254885Sdumbbell return 0; 2071254885Sdumbbell return 1; 2072254885Sdumbbell} 2073254885Sdumbbell 2074254885Sdumbbell/* This only needs to be called once at startup */ 2075254885Sdumbbellvoid 2076254885Sdumbbellradeon_atom_encoder_init(struct radeon_device *rdev) 2077254885Sdumbbell{ 2078254885Sdumbbell struct drm_device *dev = rdev->ddev; 2079254885Sdumbbell struct drm_encoder *encoder; 2080254885Sdumbbell 2081254885Sdumbbell list_for_each_entry(encoder, &dev->mode_config.encoder_list, head) { 2082254885Sdumbbell struct radeon_encoder *radeon_encoder = to_radeon_encoder(encoder); 2083254885Sdumbbell struct drm_encoder *ext_encoder = radeon_get_external_encoder(encoder); 2084254885Sdumbbell 2085254885Sdumbbell switch (radeon_encoder->encoder_id) { 2086254885Sdumbbell case ENCODER_OBJECT_ID_INTERNAL_UNIPHY: 2087254885Sdumbbell case ENCODER_OBJECT_ID_INTERNAL_UNIPHY1: 2088254885Sdumbbell case ENCODER_OBJECT_ID_INTERNAL_UNIPHY2: 2089254885Sdumbbell case ENCODER_OBJECT_ID_INTERNAL_KLDSCP_LVTMA: 2090254885Sdumbbell atombios_dig_transmitter_setup(encoder, ATOM_TRANSMITTER_ACTION_INIT, 0, 0); 2091254885Sdumbbell break; 2092254885Sdumbbell default: 2093254885Sdumbbell break; 2094254885Sdumbbell } 2095254885Sdumbbell 2096254885Sdumbbell if (ext_encoder && (ASIC_IS_DCE41(rdev) || ASIC_IS_DCE61(rdev))) 2097254885Sdumbbell atombios_external_encoder_setup(encoder, ext_encoder, 2098254885Sdumbbell EXTERNAL_ENCODER_ACTION_V3_ENCODER_INIT); 2099254885Sdumbbell } 2100254885Sdumbbell} 2101254885Sdumbbell 2102254885Sdumbbellstatic void 2103254885Sdumbbellradeon_atom_encoder_mode_set(struct drm_encoder *encoder, 2104254885Sdumbbell struct drm_display_mode *mode, 2105254885Sdumbbell struct drm_display_mode *adjusted_mode) 2106254885Sdumbbell{ 2107254885Sdumbbell struct drm_device *dev = encoder->dev; 2108254885Sdumbbell struct radeon_device *rdev = dev->dev_private; 2109254885Sdumbbell struct radeon_encoder *radeon_encoder = to_radeon_encoder(encoder); 2110254885Sdumbbell 2111254885Sdumbbell radeon_encoder->pixel_clock = adjusted_mode->clock; 2112254885Sdumbbell 2113254885Sdumbbell /* need to call this here rather than in prepare() since we need some crtc info */ 2114254885Sdumbbell radeon_atom_encoder_dpms(encoder, DRM_MODE_DPMS_OFF); 2115254885Sdumbbell 2116254885Sdumbbell if (ASIC_IS_AVIVO(rdev) && !ASIC_IS_DCE4(rdev)) { 2117254885Sdumbbell if (radeon_encoder->active_device & (ATOM_DEVICE_CV_SUPPORT | ATOM_DEVICE_TV_SUPPORT)) 2118254885Sdumbbell atombios_yuv_setup(encoder, true); 2119254885Sdumbbell else 2120254885Sdumbbell atombios_yuv_setup(encoder, false); 2121254885Sdumbbell } 2122254885Sdumbbell 2123254885Sdumbbell switch (radeon_encoder->encoder_id) { 2124254885Sdumbbell case ENCODER_OBJECT_ID_INTERNAL_TMDS1: 2125254885Sdumbbell case ENCODER_OBJECT_ID_INTERNAL_KLDSCP_TMDS1: 2126254885Sdumbbell case ENCODER_OBJECT_ID_INTERNAL_LVDS: 2127254885Sdumbbell case ENCODER_OBJECT_ID_INTERNAL_LVTM1: 2128254885Sdumbbell atombios_digital_setup(encoder, PANEL_ENCODER_ACTION_ENABLE); 2129254885Sdumbbell break; 2130254885Sdumbbell case ENCODER_OBJECT_ID_INTERNAL_UNIPHY: 2131254885Sdumbbell case ENCODER_OBJECT_ID_INTERNAL_UNIPHY1: 2132254885Sdumbbell case ENCODER_OBJECT_ID_INTERNAL_UNIPHY2: 2133254885Sdumbbell case ENCODER_OBJECT_ID_INTERNAL_KLDSCP_LVTMA: 2134254885Sdumbbell /* handled in dpms */ 2135254885Sdumbbell break; 2136254885Sdumbbell case ENCODER_OBJECT_ID_INTERNAL_DDI: 2137254885Sdumbbell case ENCODER_OBJECT_ID_INTERNAL_DVO1: 2138254885Sdumbbell case ENCODER_OBJECT_ID_INTERNAL_KLDSCP_DVO1: 2139254885Sdumbbell atombios_dvo_setup(encoder, ATOM_ENABLE); 2140254885Sdumbbell break; 2141254885Sdumbbell case ENCODER_OBJECT_ID_INTERNAL_DAC1: 2142254885Sdumbbell case ENCODER_OBJECT_ID_INTERNAL_KLDSCP_DAC1: 2143254885Sdumbbell case ENCODER_OBJECT_ID_INTERNAL_DAC2: 2144254885Sdumbbell case ENCODER_OBJECT_ID_INTERNAL_KLDSCP_DAC2: 2145254885Sdumbbell atombios_dac_setup(encoder, ATOM_ENABLE); 2146254885Sdumbbell if (radeon_encoder->devices & (ATOM_DEVICE_TV_SUPPORT | ATOM_DEVICE_CV_SUPPORT)) { 2147254885Sdumbbell if (radeon_encoder->active_device & (ATOM_DEVICE_TV_SUPPORT | ATOM_DEVICE_CV_SUPPORT)) 2148254885Sdumbbell atombios_tv_setup(encoder, ATOM_ENABLE); 2149254885Sdumbbell else 2150254885Sdumbbell atombios_tv_setup(encoder, ATOM_DISABLE); 2151254885Sdumbbell } 2152254885Sdumbbell break; 2153254885Sdumbbell } 2154254885Sdumbbell 2155254885Sdumbbell atombios_apply_encoder_quirks(encoder, adjusted_mode); 2156254885Sdumbbell 2157254885Sdumbbell if (atombios_get_encoder_mode(encoder) == ATOM_ENCODER_MODE_HDMI) { 2158254885Sdumbbell r600_hdmi_enable(encoder); 2159254885Sdumbbell if (ASIC_IS_DCE6(rdev)) 2160254885Sdumbbell ; /* TODO (use pointers instead of if-s?) */ 2161254885Sdumbbell else if (ASIC_IS_DCE4(rdev)) 2162254885Sdumbbell evergreen_hdmi_setmode(encoder, adjusted_mode); 2163254885Sdumbbell else 2164254885Sdumbbell r600_hdmi_setmode(encoder, adjusted_mode); 2165254885Sdumbbell } 2166254885Sdumbbell} 2167254885Sdumbbell 2168254885Sdumbbellstatic bool 2169254885Sdumbbellatombios_dac_load_detect(struct drm_encoder *encoder, struct drm_connector *connector) 2170254885Sdumbbell{ 2171254885Sdumbbell struct drm_device *dev = encoder->dev; 2172254885Sdumbbell struct radeon_device *rdev = dev->dev_private; 2173254885Sdumbbell struct radeon_encoder *radeon_encoder = to_radeon_encoder(encoder); 2174254885Sdumbbell struct radeon_connector *radeon_connector = to_radeon_connector(connector); 2175254885Sdumbbell 2176254885Sdumbbell if (radeon_encoder->devices & (ATOM_DEVICE_TV_SUPPORT | 2177254885Sdumbbell ATOM_DEVICE_CV_SUPPORT | 2178254885Sdumbbell ATOM_DEVICE_CRT_SUPPORT)) { 2179254885Sdumbbell DAC_LOAD_DETECTION_PS_ALLOCATION args; 2180254885Sdumbbell int index = GetIndexIntoMasterTable(COMMAND, DAC_LoadDetection); 2181254885Sdumbbell uint8_t frev, crev; 2182254885Sdumbbell 2183254885Sdumbbell memset(&args, 0, sizeof(args)); 2184254885Sdumbbell 2185254885Sdumbbell if (!atom_parse_cmd_header(rdev->mode_info.atom_context, index, &frev, &crev)) 2186254885Sdumbbell return false; 2187254885Sdumbbell 2188254885Sdumbbell args.sDacload.ucMisc = 0; 2189254885Sdumbbell 2190254885Sdumbbell if ((radeon_encoder->encoder_id == ENCODER_OBJECT_ID_INTERNAL_DAC1) || 2191254885Sdumbbell (radeon_encoder->encoder_id == ENCODER_OBJECT_ID_INTERNAL_KLDSCP_DAC1)) 2192254885Sdumbbell args.sDacload.ucDacType = ATOM_DAC_A; 2193254885Sdumbbell else 2194254885Sdumbbell args.sDacload.ucDacType = ATOM_DAC_B; 2195254885Sdumbbell 2196254885Sdumbbell if (radeon_connector->devices & ATOM_DEVICE_CRT1_SUPPORT) 2197254885Sdumbbell args.sDacload.usDeviceID = cpu_to_le16(ATOM_DEVICE_CRT1_SUPPORT); 2198254885Sdumbbell else if (radeon_connector->devices & ATOM_DEVICE_CRT2_SUPPORT) 2199254885Sdumbbell args.sDacload.usDeviceID = cpu_to_le16(ATOM_DEVICE_CRT2_SUPPORT); 2200254885Sdumbbell else if (radeon_connector->devices & ATOM_DEVICE_CV_SUPPORT) { 2201254885Sdumbbell args.sDacload.usDeviceID = cpu_to_le16(ATOM_DEVICE_CV_SUPPORT); 2202254885Sdumbbell if (crev >= 3) 2203254885Sdumbbell args.sDacload.ucMisc = DAC_LOAD_MISC_YPrPb; 2204254885Sdumbbell } else if (radeon_connector->devices & ATOM_DEVICE_TV1_SUPPORT) { 2205254885Sdumbbell args.sDacload.usDeviceID = cpu_to_le16(ATOM_DEVICE_TV1_SUPPORT); 2206254885Sdumbbell if (crev >= 3) 2207254885Sdumbbell args.sDacload.ucMisc = DAC_LOAD_MISC_YPrPb; 2208254885Sdumbbell } 2209254885Sdumbbell 2210254885Sdumbbell atom_execute_table(rdev->mode_info.atom_context, index, (uint32_t *)&args); 2211254885Sdumbbell 2212254885Sdumbbell return true; 2213254885Sdumbbell } else 2214254885Sdumbbell return false; 2215254885Sdumbbell} 2216254885Sdumbbell 2217254885Sdumbbellstatic enum drm_connector_status 2218254885Sdumbbellradeon_atom_dac_detect(struct drm_encoder *encoder, struct drm_connector *connector) 2219254885Sdumbbell{ 2220254885Sdumbbell struct drm_device *dev = encoder->dev; 2221254885Sdumbbell struct radeon_device *rdev = dev->dev_private; 2222254885Sdumbbell struct radeon_encoder *radeon_encoder = to_radeon_encoder(encoder); 2223254885Sdumbbell struct radeon_connector *radeon_connector = to_radeon_connector(connector); 2224254885Sdumbbell uint32_t bios_0_scratch; 2225254885Sdumbbell 2226254885Sdumbbell if (!atombios_dac_load_detect(encoder, connector)) { 2227254885Sdumbbell DRM_DEBUG_KMS("detect returned false \n"); 2228254885Sdumbbell return connector_status_unknown; 2229254885Sdumbbell } 2230254885Sdumbbell 2231254885Sdumbbell if (rdev->family >= CHIP_R600) 2232254885Sdumbbell bios_0_scratch = RREG32(R600_BIOS_0_SCRATCH); 2233254885Sdumbbell else 2234254885Sdumbbell bios_0_scratch = RREG32(RADEON_BIOS_0_SCRATCH); 2235254885Sdumbbell 2236254885Sdumbbell DRM_DEBUG_KMS("Bios 0 scratch %x %08x\n", bios_0_scratch, radeon_encoder->devices); 2237254885Sdumbbell if (radeon_connector->devices & ATOM_DEVICE_CRT1_SUPPORT) { 2238254885Sdumbbell if (bios_0_scratch & ATOM_S0_CRT1_MASK) 2239254885Sdumbbell return connector_status_connected; 2240254885Sdumbbell } 2241254885Sdumbbell if (radeon_connector->devices & ATOM_DEVICE_CRT2_SUPPORT) { 2242254885Sdumbbell if (bios_0_scratch & ATOM_S0_CRT2_MASK) 2243254885Sdumbbell return connector_status_connected; 2244254885Sdumbbell } 2245254885Sdumbbell if (radeon_connector->devices & ATOM_DEVICE_CV_SUPPORT) { 2246254885Sdumbbell if (bios_0_scratch & (ATOM_S0_CV_MASK|ATOM_S0_CV_MASK_A)) 2247254885Sdumbbell return connector_status_connected; 2248254885Sdumbbell } 2249254885Sdumbbell if (radeon_connector->devices & ATOM_DEVICE_TV1_SUPPORT) { 2250254885Sdumbbell if (bios_0_scratch & (ATOM_S0_TV1_COMPOSITE | ATOM_S0_TV1_COMPOSITE_A)) 2251254885Sdumbbell return connector_status_connected; /* CTV */ 2252254885Sdumbbell else if (bios_0_scratch & (ATOM_S0_TV1_SVIDEO | ATOM_S0_TV1_SVIDEO_A)) 2253254885Sdumbbell return connector_status_connected; /* STV */ 2254254885Sdumbbell } 2255254885Sdumbbell return connector_status_disconnected; 2256254885Sdumbbell} 2257254885Sdumbbell 2258254885Sdumbbellstatic enum drm_connector_status 2259254885Sdumbbellradeon_atom_dig_detect(struct drm_encoder *encoder, struct drm_connector *connector) 2260254885Sdumbbell{ 2261254885Sdumbbell struct drm_device *dev = encoder->dev; 2262254885Sdumbbell struct radeon_device *rdev = dev->dev_private; 2263254885Sdumbbell struct radeon_encoder *radeon_encoder = to_radeon_encoder(encoder); 2264254885Sdumbbell struct radeon_connector *radeon_connector = to_radeon_connector(connector); 2265254885Sdumbbell struct drm_encoder *ext_encoder = radeon_get_external_encoder(encoder); 2266254885Sdumbbell u32 bios_0_scratch; 2267254885Sdumbbell 2268254885Sdumbbell if (!ASIC_IS_DCE4(rdev)) 2269254885Sdumbbell return connector_status_unknown; 2270254885Sdumbbell 2271254885Sdumbbell if (!ext_encoder) 2272254885Sdumbbell return connector_status_unknown; 2273254885Sdumbbell 2274254885Sdumbbell if ((radeon_connector->devices & ATOM_DEVICE_CRT_SUPPORT) == 0) 2275254885Sdumbbell return connector_status_unknown; 2276254885Sdumbbell 2277254885Sdumbbell /* load detect on the dp bridge */ 2278254885Sdumbbell atombios_external_encoder_setup(encoder, ext_encoder, 2279254885Sdumbbell EXTERNAL_ENCODER_ACTION_V3_DACLOAD_DETECTION); 2280254885Sdumbbell 2281254885Sdumbbell bios_0_scratch = RREG32(R600_BIOS_0_SCRATCH); 2282254885Sdumbbell 2283254885Sdumbbell DRM_DEBUG_KMS("Bios 0 scratch %x %08x\n", bios_0_scratch, radeon_encoder->devices); 2284254885Sdumbbell if (radeon_connector->devices & ATOM_DEVICE_CRT1_SUPPORT) { 2285254885Sdumbbell if (bios_0_scratch & ATOM_S0_CRT1_MASK) 2286254885Sdumbbell return connector_status_connected; 2287254885Sdumbbell } 2288254885Sdumbbell if (radeon_connector->devices & ATOM_DEVICE_CRT2_SUPPORT) { 2289254885Sdumbbell if (bios_0_scratch & ATOM_S0_CRT2_MASK) 2290254885Sdumbbell return connector_status_connected; 2291254885Sdumbbell } 2292254885Sdumbbell if (radeon_connector->devices & ATOM_DEVICE_CV_SUPPORT) { 2293254885Sdumbbell if (bios_0_scratch & (ATOM_S0_CV_MASK|ATOM_S0_CV_MASK_A)) 2294254885Sdumbbell return connector_status_connected; 2295254885Sdumbbell } 2296254885Sdumbbell if (radeon_connector->devices & ATOM_DEVICE_TV1_SUPPORT) { 2297254885Sdumbbell if (bios_0_scratch & (ATOM_S0_TV1_COMPOSITE | ATOM_S0_TV1_COMPOSITE_A)) 2298254885Sdumbbell return connector_status_connected; /* CTV */ 2299254885Sdumbbell else if (bios_0_scratch & (ATOM_S0_TV1_SVIDEO | ATOM_S0_TV1_SVIDEO_A)) 2300254885Sdumbbell return connector_status_connected; /* STV */ 2301254885Sdumbbell } 2302254885Sdumbbell return connector_status_disconnected; 2303254885Sdumbbell} 2304254885Sdumbbell 2305254885Sdumbbellvoid 2306254885Sdumbbellradeon_atom_ext_encoder_setup_ddc(struct drm_encoder *encoder) 2307254885Sdumbbell{ 2308254885Sdumbbell struct drm_encoder *ext_encoder = radeon_get_external_encoder(encoder); 2309254885Sdumbbell 2310254885Sdumbbell if (ext_encoder) 2311254885Sdumbbell /* ddc_setup on the dp bridge */ 2312254885Sdumbbell atombios_external_encoder_setup(encoder, ext_encoder, 2313254885Sdumbbell EXTERNAL_ENCODER_ACTION_V3_DDC_SETUP); 2314254885Sdumbbell 2315254885Sdumbbell} 2316254885Sdumbbell 2317254885Sdumbbellstatic void radeon_atom_encoder_prepare(struct drm_encoder *encoder) 2318254885Sdumbbell{ 2319254885Sdumbbell struct radeon_device *rdev = encoder->dev->dev_private; 2320254885Sdumbbell struct radeon_encoder *radeon_encoder = to_radeon_encoder(encoder); 2321254885Sdumbbell struct drm_connector *connector = radeon_get_connector_for_encoder(encoder); 2322254885Sdumbbell 2323254885Sdumbbell if ((radeon_encoder->active_device & 2324254885Sdumbbell (ATOM_DEVICE_DFP_SUPPORT | ATOM_DEVICE_LCD_SUPPORT)) || 2325254885Sdumbbell (radeon_encoder_get_dp_bridge_encoder_id(encoder) != 2326254885Sdumbbell ENCODER_OBJECT_ID_NONE)) { 2327254885Sdumbbell struct radeon_encoder_atom_dig *dig = radeon_encoder->enc_priv; 2328254885Sdumbbell if (dig) { 2329254885Sdumbbell dig->dig_encoder = radeon_atom_pick_dig_encoder(encoder); 2330254885Sdumbbell if (radeon_encoder->active_device & ATOM_DEVICE_DFP_SUPPORT) { 2331254885Sdumbbell if (rdev->family >= CHIP_R600) 2332254885Sdumbbell dig->afmt = rdev->mode_info.afmt[dig->dig_encoder]; 2333254885Sdumbbell else 2334254885Sdumbbell /* RS600/690/740 have only 1 afmt block */ 2335254885Sdumbbell dig->afmt = rdev->mode_info.afmt[0]; 2336254885Sdumbbell } 2337254885Sdumbbell } 2338254885Sdumbbell } 2339254885Sdumbbell 2340254885Sdumbbell radeon_atom_output_lock(encoder, true); 2341254885Sdumbbell 2342254885Sdumbbell if (connector) { 2343254885Sdumbbell struct radeon_connector *radeon_connector = to_radeon_connector(connector); 2344254885Sdumbbell 2345254885Sdumbbell /* select the clock/data port if it uses a router */ 2346254885Sdumbbell if (radeon_connector->router.cd_valid) 2347254885Sdumbbell radeon_router_select_cd_port(radeon_connector); 2348254885Sdumbbell 2349254885Sdumbbell /* turn eDP panel on for mode set */ 2350254885Sdumbbell if (connector->connector_type == DRM_MODE_CONNECTOR_eDP) 2351254885Sdumbbell atombios_set_edp_panel_power(connector, 2352254885Sdumbbell ATOM_TRANSMITTER_ACTION_POWER_ON); 2353254885Sdumbbell } 2354254885Sdumbbell 2355254885Sdumbbell /* this is needed for the pll/ss setup to work correctly in some cases */ 2356254885Sdumbbell atombios_set_encoder_crtc_source(encoder); 2357254885Sdumbbell} 2358254885Sdumbbell 2359254885Sdumbbellstatic void radeon_atom_encoder_commit(struct drm_encoder *encoder) 2360254885Sdumbbell{ 2361254885Sdumbbell /* need to call this here as we need the crtc set up */ 2362254885Sdumbbell radeon_atom_encoder_dpms(encoder, DRM_MODE_DPMS_ON); 2363254885Sdumbbell radeon_atom_output_lock(encoder, false); 2364254885Sdumbbell} 2365254885Sdumbbell 2366254885Sdumbbellstatic void radeon_atom_encoder_disable(struct drm_encoder *encoder) 2367254885Sdumbbell{ 2368254885Sdumbbell struct drm_device *dev = encoder->dev; 2369254885Sdumbbell struct radeon_device *rdev = dev->dev_private; 2370254885Sdumbbell struct radeon_encoder *radeon_encoder = to_radeon_encoder(encoder); 2371254885Sdumbbell struct radeon_encoder_atom_dig *dig; 2372254885Sdumbbell 2373254885Sdumbbell /* check for pre-DCE3 cards with shared encoders; 2374254885Sdumbbell * can't really use the links individually, so don't disable 2375254885Sdumbbell * the encoder if it's in use by another connector 2376254885Sdumbbell */ 2377254885Sdumbbell if (!ASIC_IS_DCE3(rdev)) { 2378254885Sdumbbell struct drm_encoder *other_encoder; 2379254885Sdumbbell struct radeon_encoder *other_radeon_encoder; 2380254885Sdumbbell 2381254885Sdumbbell list_for_each_entry(other_encoder, &dev->mode_config.encoder_list, head) { 2382254885Sdumbbell other_radeon_encoder = to_radeon_encoder(other_encoder); 2383254885Sdumbbell if ((radeon_encoder->encoder_id == other_radeon_encoder->encoder_id) && 2384254885Sdumbbell drm_helper_encoder_in_use(other_encoder)) 2385254885Sdumbbell goto disable_done; 2386254885Sdumbbell } 2387254885Sdumbbell } 2388254885Sdumbbell 2389254885Sdumbbell radeon_atom_encoder_dpms(encoder, DRM_MODE_DPMS_OFF); 2390254885Sdumbbell 2391254885Sdumbbell switch (radeon_encoder->encoder_id) { 2392254885Sdumbbell case ENCODER_OBJECT_ID_INTERNAL_TMDS1: 2393254885Sdumbbell case ENCODER_OBJECT_ID_INTERNAL_KLDSCP_TMDS1: 2394254885Sdumbbell case ENCODER_OBJECT_ID_INTERNAL_LVDS: 2395254885Sdumbbell case ENCODER_OBJECT_ID_INTERNAL_LVTM1: 2396254885Sdumbbell atombios_digital_setup(encoder, PANEL_ENCODER_ACTION_DISABLE); 2397254885Sdumbbell break; 2398254885Sdumbbell case ENCODER_OBJECT_ID_INTERNAL_UNIPHY: 2399254885Sdumbbell case ENCODER_OBJECT_ID_INTERNAL_UNIPHY1: 2400254885Sdumbbell case ENCODER_OBJECT_ID_INTERNAL_UNIPHY2: 2401254885Sdumbbell case ENCODER_OBJECT_ID_INTERNAL_KLDSCP_LVTMA: 2402254885Sdumbbell /* handled in dpms */ 2403254885Sdumbbell break; 2404254885Sdumbbell case ENCODER_OBJECT_ID_INTERNAL_DDI: 2405254885Sdumbbell case ENCODER_OBJECT_ID_INTERNAL_DVO1: 2406254885Sdumbbell case ENCODER_OBJECT_ID_INTERNAL_KLDSCP_DVO1: 2407254885Sdumbbell atombios_dvo_setup(encoder, ATOM_DISABLE); 2408254885Sdumbbell break; 2409254885Sdumbbell case ENCODER_OBJECT_ID_INTERNAL_DAC1: 2410254885Sdumbbell case ENCODER_OBJECT_ID_INTERNAL_KLDSCP_DAC1: 2411254885Sdumbbell case ENCODER_OBJECT_ID_INTERNAL_DAC2: 2412254885Sdumbbell case ENCODER_OBJECT_ID_INTERNAL_KLDSCP_DAC2: 2413254885Sdumbbell atombios_dac_setup(encoder, ATOM_DISABLE); 2414254885Sdumbbell if (radeon_encoder->devices & (ATOM_DEVICE_TV_SUPPORT | ATOM_DEVICE_CV_SUPPORT)) 2415254885Sdumbbell atombios_tv_setup(encoder, ATOM_DISABLE); 2416254885Sdumbbell break; 2417254885Sdumbbell } 2418254885Sdumbbell 2419254885Sdumbbelldisable_done: 2420254885Sdumbbell if (radeon_encoder_is_digital(encoder)) { 2421254885Sdumbbell if (atombios_get_encoder_mode(encoder) == ATOM_ENCODER_MODE_HDMI) 2422254885Sdumbbell r600_hdmi_disable(encoder); 2423254885Sdumbbell dig = radeon_encoder->enc_priv; 2424254885Sdumbbell dig->dig_encoder = -1; 2425254885Sdumbbell } 2426254885Sdumbbell radeon_encoder->active_device = 0; 2427254885Sdumbbell} 2428254885Sdumbbell 2429254885Sdumbbell/* these are handled by the primary encoders */ 2430254885Sdumbbellstatic void radeon_atom_ext_prepare(struct drm_encoder *encoder) 2431254885Sdumbbell{ 2432254885Sdumbbell 2433254885Sdumbbell} 2434254885Sdumbbell 2435254885Sdumbbellstatic void radeon_atom_ext_commit(struct drm_encoder *encoder) 2436254885Sdumbbell{ 2437254885Sdumbbell 2438254885Sdumbbell} 2439254885Sdumbbell 2440254885Sdumbbellstatic void 2441254885Sdumbbellradeon_atom_ext_mode_set(struct drm_encoder *encoder, 2442254885Sdumbbell struct drm_display_mode *mode, 2443254885Sdumbbell struct drm_display_mode *adjusted_mode) 2444254885Sdumbbell{ 2445254885Sdumbbell 2446254885Sdumbbell} 2447254885Sdumbbell 2448254885Sdumbbellstatic void radeon_atom_ext_disable(struct drm_encoder *encoder) 2449254885Sdumbbell{ 2450254885Sdumbbell 2451254885Sdumbbell} 2452254885Sdumbbell 2453254885Sdumbbellstatic void 2454254885Sdumbbellradeon_atom_ext_dpms(struct drm_encoder *encoder, int mode) 2455254885Sdumbbell{ 2456254885Sdumbbell 2457254885Sdumbbell} 2458254885Sdumbbell 2459254885Sdumbbellstatic bool radeon_atom_ext_mode_fixup(struct drm_encoder *encoder, 2460280183Sdumbbell const struct drm_display_mode *mode, 2461254885Sdumbbell struct drm_display_mode *adjusted_mode) 2462254885Sdumbbell{ 2463254885Sdumbbell return true; 2464254885Sdumbbell} 2465254885Sdumbbell 2466254885Sdumbbellstatic const struct drm_encoder_helper_funcs radeon_atom_ext_helper_funcs = { 2467254885Sdumbbell .dpms = radeon_atom_ext_dpms, 2468254885Sdumbbell .mode_fixup = radeon_atom_ext_mode_fixup, 2469254885Sdumbbell .prepare = radeon_atom_ext_prepare, 2470254885Sdumbbell .mode_set = radeon_atom_ext_mode_set, 2471254885Sdumbbell .commit = radeon_atom_ext_commit, 2472254885Sdumbbell .disable = radeon_atom_ext_disable, 2473254885Sdumbbell /* no detect for TMDS/LVDS yet */ 2474254885Sdumbbell}; 2475254885Sdumbbell 2476254885Sdumbbellstatic const struct drm_encoder_helper_funcs radeon_atom_dig_helper_funcs = { 2477254885Sdumbbell .dpms = radeon_atom_encoder_dpms, 2478254885Sdumbbell .mode_fixup = radeon_atom_mode_fixup, 2479254885Sdumbbell .prepare = radeon_atom_encoder_prepare, 2480254885Sdumbbell .mode_set = radeon_atom_encoder_mode_set, 2481254885Sdumbbell .commit = radeon_atom_encoder_commit, 2482254885Sdumbbell .disable = radeon_atom_encoder_disable, 2483254885Sdumbbell .detect = radeon_atom_dig_detect, 2484254885Sdumbbell}; 2485254885Sdumbbell 2486254885Sdumbbellstatic const struct drm_encoder_helper_funcs radeon_atom_dac_helper_funcs = { 2487254885Sdumbbell .dpms = radeon_atom_encoder_dpms, 2488254885Sdumbbell .mode_fixup = radeon_atom_mode_fixup, 2489254885Sdumbbell .prepare = radeon_atom_encoder_prepare, 2490254885Sdumbbell .mode_set = radeon_atom_encoder_mode_set, 2491254885Sdumbbell .commit = radeon_atom_encoder_commit, 2492254885Sdumbbell .detect = radeon_atom_dac_detect, 2493254885Sdumbbell}; 2494254885Sdumbbell 2495254885Sdumbbellvoid radeon_enc_destroy(struct drm_encoder *encoder) 2496254885Sdumbbell{ 2497254885Sdumbbell struct radeon_encoder *radeon_encoder = to_radeon_encoder(encoder); 2498254885Sdumbbell if (radeon_encoder->devices & (ATOM_DEVICE_LCD_SUPPORT)) 2499254885Sdumbbell radeon_atom_backlight_exit(radeon_encoder); 2500254885Sdumbbell free(radeon_encoder->enc_priv, DRM_MEM_DRIVER); 2501254885Sdumbbell drm_encoder_cleanup(encoder); 2502254885Sdumbbell free(radeon_encoder, DRM_MEM_DRIVER); 2503254885Sdumbbell} 2504254885Sdumbbell 2505254885Sdumbbellstatic const struct drm_encoder_funcs radeon_atom_enc_funcs = { 2506254885Sdumbbell .destroy = radeon_enc_destroy, 2507254885Sdumbbell}; 2508254885Sdumbbell 2509254885Sdumbbellstatic struct radeon_encoder_atom_dac * 2510254885Sdumbbellradeon_atombios_set_dac_info(struct radeon_encoder *radeon_encoder) 2511254885Sdumbbell{ 2512254885Sdumbbell struct drm_device *dev = radeon_encoder->base.dev; 2513254885Sdumbbell struct radeon_device *rdev = dev->dev_private; 2514254885Sdumbbell struct radeon_encoder_atom_dac *dac = malloc(sizeof(struct radeon_encoder_atom_dac), 2515280183Sdumbbell DRM_MEM_DRIVER, M_NOWAIT | M_ZERO); 2516254885Sdumbbell 2517254885Sdumbbell if (!dac) 2518254885Sdumbbell return NULL; 2519254885Sdumbbell 2520254885Sdumbbell dac->tv_std = radeon_atombios_get_tv_info(rdev); 2521254885Sdumbbell return dac; 2522254885Sdumbbell} 2523254885Sdumbbell 2524254885Sdumbbellstatic struct radeon_encoder_atom_dig * 2525254885Sdumbbellradeon_atombios_set_dig_info(struct radeon_encoder *radeon_encoder) 2526254885Sdumbbell{ 2527254885Sdumbbell int encoder_enum = (radeon_encoder->encoder_enum & ENUM_ID_MASK) >> ENUM_ID_SHIFT; 2528254885Sdumbbell struct radeon_encoder_atom_dig *dig = malloc(sizeof(struct radeon_encoder_atom_dig), 2529280183Sdumbbell DRM_MEM_DRIVER, M_NOWAIT | M_ZERO); 2530254885Sdumbbell 2531254885Sdumbbell if (!dig) 2532254885Sdumbbell return NULL; 2533254885Sdumbbell 2534254885Sdumbbell /* coherent mode by default */ 2535254885Sdumbbell dig->coherent_mode = true; 2536254885Sdumbbell dig->dig_encoder = -1; 2537254885Sdumbbell 2538254885Sdumbbell if (encoder_enum == 2) 2539254885Sdumbbell dig->linkb = true; 2540254885Sdumbbell else 2541254885Sdumbbell dig->linkb = false; 2542254885Sdumbbell 2543254885Sdumbbell return dig; 2544254885Sdumbbell} 2545254885Sdumbbell 2546254885Sdumbbellvoid 2547254885Sdumbbellradeon_add_atom_encoder(struct drm_device *dev, 2548254885Sdumbbell uint32_t encoder_enum, 2549254885Sdumbbell uint32_t supported_device, 2550254885Sdumbbell u16 caps) 2551254885Sdumbbell{ 2552254885Sdumbbell struct radeon_device *rdev = dev->dev_private; 2553254885Sdumbbell struct drm_encoder *encoder; 2554254885Sdumbbell struct radeon_encoder *radeon_encoder; 2555254885Sdumbbell 2556254885Sdumbbell /* see if we already added it */ 2557254885Sdumbbell list_for_each_entry(encoder, &dev->mode_config.encoder_list, head) { 2558254885Sdumbbell radeon_encoder = to_radeon_encoder(encoder); 2559254885Sdumbbell if (radeon_encoder->encoder_enum == encoder_enum) { 2560254885Sdumbbell radeon_encoder->devices |= supported_device; 2561254885Sdumbbell return; 2562254885Sdumbbell } 2563254885Sdumbbell 2564254885Sdumbbell } 2565254885Sdumbbell 2566254885Sdumbbell /* add a new one */ 2567254885Sdumbbell radeon_encoder = malloc(sizeof(struct radeon_encoder), 2568280183Sdumbbell DRM_MEM_DRIVER, M_NOWAIT | M_ZERO); 2569254885Sdumbbell if (!radeon_encoder) 2570254885Sdumbbell return; 2571254885Sdumbbell 2572254885Sdumbbell encoder = &radeon_encoder->base; 2573254885Sdumbbell switch (rdev->num_crtc) { 2574254885Sdumbbell case 1: 2575254885Sdumbbell encoder->possible_crtcs = 0x1; 2576254885Sdumbbell break; 2577254885Sdumbbell case 2: 2578254885Sdumbbell default: 2579254885Sdumbbell encoder->possible_crtcs = 0x3; 2580254885Sdumbbell break; 2581254885Sdumbbell case 4: 2582254885Sdumbbell encoder->possible_crtcs = 0xf; 2583254885Sdumbbell break; 2584254885Sdumbbell case 6: 2585254885Sdumbbell encoder->possible_crtcs = 0x3f; 2586254885Sdumbbell break; 2587254885Sdumbbell } 2588254885Sdumbbell 2589254885Sdumbbell radeon_encoder->enc_priv = NULL; 2590254885Sdumbbell 2591254885Sdumbbell radeon_encoder->encoder_enum = encoder_enum; 2592254885Sdumbbell radeon_encoder->encoder_id = (encoder_enum & OBJECT_ID_MASK) >> OBJECT_ID_SHIFT; 2593254885Sdumbbell radeon_encoder->devices = supported_device; 2594254885Sdumbbell radeon_encoder->rmx_type = RMX_OFF; 2595254885Sdumbbell radeon_encoder->underscan_type = UNDERSCAN_OFF; 2596254885Sdumbbell radeon_encoder->is_ext_encoder = false; 2597254885Sdumbbell radeon_encoder->caps = caps; 2598254885Sdumbbell 2599254885Sdumbbell switch (radeon_encoder->encoder_id) { 2600254885Sdumbbell case ENCODER_OBJECT_ID_INTERNAL_LVDS: 2601254885Sdumbbell case ENCODER_OBJECT_ID_INTERNAL_TMDS1: 2602254885Sdumbbell case ENCODER_OBJECT_ID_INTERNAL_KLDSCP_TMDS1: 2603254885Sdumbbell case ENCODER_OBJECT_ID_INTERNAL_LVTM1: 2604254885Sdumbbell if (radeon_encoder->devices & (ATOM_DEVICE_LCD_SUPPORT)) { 2605254885Sdumbbell radeon_encoder->rmx_type = RMX_FULL; 2606254885Sdumbbell drm_encoder_init(dev, encoder, &radeon_atom_enc_funcs, DRM_MODE_ENCODER_LVDS); 2607254885Sdumbbell radeon_encoder->enc_priv = radeon_atombios_get_lvds_info(radeon_encoder); 2608254885Sdumbbell } else { 2609254885Sdumbbell drm_encoder_init(dev, encoder, &radeon_atom_enc_funcs, DRM_MODE_ENCODER_TMDS); 2610254885Sdumbbell radeon_encoder->enc_priv = radeon_atombios_set_dig_info(radeon_encoder); 2611254885Sdumbbell } 2612254885Sdumbbell drm_encoder_helper_add(encoder, &radeon_atom_dig_helper_funcs); 2613254885Sdumbbell break; 2614254885Sdumbbell case ENCODER_OBJECT_ID_INTERNAL_DAC1: 2615254885Sdumbbell drm_encoder_init(dev, encoder, &radeon_atom_enc_funcs, DRM_MODE_ENCODER_DAC); 2616254885Sdumbbell radeon_encoder->enc_priv = radeon_atombios_set_dac_info(radeon_encoder); 2617254885Sdumbbell drm_encoder_helper_add(encoder, &radeon_atom_dac_helper_funcs); 2618254885Sdumbbell break; 2619254885Sdumbbell case ENCODER_OBJECT_ID_INTERNAL_DAC2: 2620254885Sdumbbell case ENCODER_OBJECT_ID_INTERNAL_KLDSCP_DAC1: 2621254885Sdumbbell case ENCODER_OBJECT_ID_INTERNAL_KLDSCP_DAC2: 2622254885Sdumbbell drm_encoder_init(dev, encoder, &radeon_atom_enc_funcs, DRM_MODE_ENCODER_TVDAC); 2623254885Sdumbbell radeon_encoder->enc_priv = radeon_atombios_set_dac_info(radeon_encoder); 2624254885Sdumbbell drm_encoder_helper_add(encoder, &radeon_atom_dac_helper_funcs); 2625254885Sdumbbell break; 2626254885Sdumbbell case ENCODER_OBJECT_ID_INTERNAL_DVO1: 2627254885Sdumbbell case ENCODER_OBJECT_ID_INTERNAL_KLDSCP_DVO1: 2628254885Sdumbbell case ENCODER_OBJECT_ID_INTERNAL_DDI: 2629254885Sdumbbell case ENCODER_OBJECT_ID_INTERNAL_UNIPHY: 2630254885Sdumbbell case ENCODER_OBJECT_ID_INTERNAL_KLDSCP_LVTMA: 2631254885Sdumbbell case ENCODER_OBJECT_ID_INTERNAL_UNIPHY1: 2632254885Sdumbbell case ENCODER_OBJECT_ID_INTERNAL_UNIPHY2: 2633254885Sdumbbell if (radeon_encoder->devices & (ATOM_DEVICE_LCD_SUPPORT)) { 2634254885Sdumbbell radeon_encoder->rmx_type = RMX_FULL; 2635254885Sdumbbell drm_encoder_init(dev, encoder, &radeon_atom_enc_funcs, DRM_MODE_ENCODER_LVDS); 2636254885Sdumbbell radeon_encoder->enc_priv = radeon_atombios_get_lvds_info(radeon_encoder); 2637254885Sdumbbell } else if (radeon_encoder->devices & (ATOM_DEVICE_CRT_SUPPORT)) { 2638254885Sdumbbell drm_encoder_init(dev, encoder, &radeon_atom_enc_funcs, DRM_MODE_ENCODER_DAC); 2639254885Sdumbbell radeon_encoder->enc_priv = radeon_atombios_set_dig_info(radeon_encoder); 2640254885Sdumbbell } else { 2641254885Sdumbbell drm_encoder_init(dev, encoder, &radeon_atom_enc_funcs, DRM_MODE_ENCODER_TMDS); 2642254885Sdumbbell radeon_encoder->enc_priv = radeon_atombios_set_dig_info(radeon_encoder); 2643254885Sdumbbell } 2644254885Sdumbbell drm_encoder_helper_add(encoder, &radeon_atom_dig_helper_funcs); 2645254885Sdumbbell break; 2646254885Sdumbbell case ENCODER_OBJECT_ID_SI170B: 2647254885Sdumbbell case ENCODER_OBJECT_ID_CH7303: 2648254885Sdumbbell case ENCODER_OBJECT_ID_EXTERNAL_SDVOA: 2649254885Sdumbbell case ENCODER_OBJECT_ID_EXTERNAL_SDVOB: 2650254885Sdumbbell case ENCODER_OBJECT_ID_TITFP513: 2651254885Sdumbbell case ENCODER_OBJECT_ID_VT1623: 2652254885Sdumbbell case ENCODER_OBJECT_ID_HDMI_SI1930: 2653254885Sdumbbell case ENCODER_OBJECT_ID_TRAVIS: 2654254885Sdumbbell case ENCODER_OBJECT_ID_NUTMEG: 2655254885Sdumbbell /* these are handled by the primary encoders */ 2656254885Sdumbbell radeon_encoder->is_ext_encoder = true; 2657254885Sdumbbell if (radeon_encoder->devices & (ATOM_DEVICE_LCD_SUPPORT)) 2658254885Sdumbbell drm_encoder_init(dev, encoder, &radeon_atom_enc_funcs, DRM_MODE_ENCODER_LVDS); 2659254885Sdumbbell else if (radeon_encoder->devices & (ATOM_DEVICE_CRT_SUPPORT)) 2660254885Sdumbbell drm_encoder_init(dev, encoder, &radeon_atom_enc_funcs, DRM_MODE_ENCODER_DAC); 2661254885Sdumbbell else 2662254885Sdumbbell drm_encoder_init(dev, encoder, &radeon_atom_enc_funcs, DRM_MODE_ENCODER_TMDS); 2663254885Sdumbbell drm_encoder_helper_add(encoder, &radeon_atom_ext_helper_funcs); 2664254885Sdumbbell break; 2665254885Sdumbbell } 2666254885Sdumbbell} 2667