2265 lines · c
1/*2 * Copyright 2007-8 Advanced Micro Devices, Inc.3 * Copyright 2008 Red Hat Inc.4 *5 * Permission is hereby granted, free of charge, to any person obtaining a6 * copy of this software and associated documentation files (the "Software"),7 * to deal in the Software without restriction, including without limitation8 * the rights to use, copy, modify, merge, publish, distribute, sublicense,9 * and/or sell copies of the Software, and to permit persons to whom the10 * Software is furnished to do so, subject to the following conditions:11 *12 * The above copyright notice and this permission notice shall be included in13 * all copies or substantial portions of the Software.14 *15 * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR16 * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,17 * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL18 * THE COPYRIGHT HOLDER(S) OR AUTHOR(S) BE LIABLE FOR ANY CLAIM, DAMAGES OR19 * OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE,20 * ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR21 * OTHER DEALINGS IN THE SOFTWARE.22 *23 * Authors: Dave Airlie24 * Alex Deucher25 */26 27#include <drm/drm_fixed.h>28#include <drm/drm_fourcc.h>29#include <drm/drm_framebuffer.h>30#include <drm/drm_modeset_helper_vtables.h>31#include <drm/drm_vblank.h>32#include <drm/radeon_drm.h>33 34#include "radeon.h"35#include "atom.h"36#include "atom-bits.h"37 38static void atombios_overscan_setup(struct drm_crtc *crtc,39 struct drm_display_mode *mode,40 struct drm_display_mode *adjusted_mode)41{42 struct drm_device *dev = crtc->dev;43 struct radeon_device *rdev = dev->dev_private;44 struct radeon_crtc *radeon_crtc = to_radeon_crtc(crtc);45 SET_CRTC_OVERSCAN_PS_ALLOCATION args;46 int index = GetIndexIntoMasterTable(COMMAND, SetCRTC_OverScan);47 int a1, a2;48 49 memset(&args, 0, sizeof(args));50 51 args.ucCRTC = radeon_crtc->crtc_id;52 53 switch (radeon_crtc->rmx_type) {54 case RMX_CENTER:55 args.usOverscanTop = cpu_to_le16((adjusted_mode->crtc_vdisplay - mode->crtc_vdisplay) / 2);56 args.usOverscanBottom = cpu_to_le16((adjusted_mode->crtc_vdisplay - mode->crtc_vdisplay) / 2);57 args.usOverscanLeft = cpu_to_le16((adjusted_mode->crtc_hdisplay - mode->crtc_hdisplay) / 2);58 args.usOverscanRight = cpu_to_le16((adjusted_mode->crtc_hdisplay - mode->crtc_hdisplay) / 2);59 break;60 case RMX_ASPECT:61 a1 = mode->crtc_vdisplay * adjusted_mode->crtc_hdisplay;62 a2 = adjusted_mode->crtc_vdisplay * mode->crtc_hdisplay;63 64 if (a1 > a2) {65 args.usOverscanLeft = cpu_to_le16((adjusted_mode->crtc_hdisplay - (a2 / mode->crtc_vdisplay)) / 2);66 args.usOverscanRight = cpu_to_le16((adjusted_mode->crtc_hdisplay - (a2 / mode->crtc_vdisplay)) / 2);67 } else if (a2 > a1) {68 args.usOverscanTop = cpu_to_le16((adjusted_mode->crtc_vdisplay - (a1 / mode->crtc_hdisplay)) / 2);69 args.usOverscanBottom = cpu_to_le16((adjusted_mode->crtc_vdisplay - (a1 / mode->crtc_hdisplay)) / 2);70 }71 break;72 case RMX_FULL:73 default:74 args.usOverscanRight = cpu_to_le16(radeon_crtc->h_border);75 args.usOverscanLeft = cpu_to_le16(radeon_crtc->h_border);76 args.usOverscanBottom = cpu_to_le16(radeon_crtc->v_border);77 args.usOverscanTop = cpu_to_le16(radeon_crtc->v_border);78 break;79 }80 atom_execute_table(rdev->mode_info.atom_context, index, (uint32_t *)&args, sizeof(args));81}82 83static void atombios_scaler_setup(struct drm_crtc *crtc)84{85 struct drm_device *dev = crtc->dev;86 struct radeon_device *rdev = dev->dev_private;87 struct radeon_crtc *radeon_crtc = to_radeon_crtc(crtc);88 ENABLE_SCALER_PS_ALLOCATION args;89 int index = GetIndexIntoMasterTable(COMMAND, EnableScaler);90 struct radeon_encoder *radeon_encoder =91 to_radeon_encoder(radeon_crtc->encoder);92 /* fixme - fill in enc_priv for atom dac */93 enum radeon_tv_std tv_std = TV_STD_NTSC;94 bool is_tv = false, is_cv = false;95 96 if (!ASIC_IS_AVIVO(rdev) && radeon_crtc->crtc_id)97 return;98 99 if (radeon_encoder->active_device & ATOM_DEVICE_TV_SUPPORT) {100 struct radeon_encoder_atom_dac *tv_dac = radeon_encoder->enc_priv;101 tv_std = tv_dac->tv_std;102 is_tv = true;103 }104 105 memset(&args, 0, sizeof(args));106 107 args.ucScaler = radeon_crtc->crtc_id;108 109 if (is_tv) {110 switch (tv_std) {111 case TV_STD_NTSC:112 default:113 args.ucTVStandard = ATOM_TV_NTSC;114 break;115 case TV_STD_PAL:116 args.ucTVStandard = ATOM_TV_PAL;117 break;118 case TV_STD_PAL_M:119 args.ucTVStandard = ATOM_TV_PALM;120 break;121 case TV_STD_PAL_60:122 args.ucTVStandard = ATOM_TV_PAL60;123 break;124 case TV_STD_NTSC_J:125 args.ucTVStandard = ATOM_TV_NTSCJ;126 break;127 case TV_STD_SCART_PAL:128 args.ucTVStandard = ATOM_TV_PAL; /* ??? */129 break;130 case TV_STD_SECAM:131 args.ucTVStandard = ATOM_TV_SECAM;132 break;133 case TV_STD_PAL_CN:134 args.ucTVStandard = ATOM_TV_PALCN;135 break;136 }137 args.ucEnable = SCALER_ENABLE_MULTITAP_MODE;138 } else if (is_cv) {139 args.ucTVStandard = ATOM_TV_CV;140 args.ucEnable = SCALER_ENABLE_MULTITAP_MODE;141 } else {142 switch (radeon_crtc->rmx_type) {143 case RMX_FULL:144 args.ucEnable = ATOM_SCALER_EXPANSION;145 break;146 case RMX_CENTER:147 args.ucEnable = ATOM_SCALER_CENTER;148 break;149 case RMX_ASPECT:150 args.ucEnable = ATOM_SCALER_EXPANSION;151 break;152 default:153 if (ASIC_IS_AVIVO(rdev))154 args.ucEnable = ATOM_SCALER_DISABLE;155 else156 args.ucEnable = ATOM_SCALER_CENTER;157 break;158 }159 }160 atom_execute_table(rdev->mode_info.atom_context, index, (uint32_t *)&args, sizeof(args));161 if ((is_tv || is_cv)162 && rdev->family >= CHIP_RV515 && rdev->family <= CHIP_R580) {163 atom_rv515_force_tv_scaler(rdev, radeon_crtc);164 }165}166 167static void atombios_lock_crtc(struct drm_crtc *crtc, int lock)168{169 struct radeon_crtc *radeon_crtc = to_radeon_crtc(crtc);170 struct drm_device *dev = crtc->dev;171 struct radeon_device *rdev = dev->dev_private;172 int index =173 GetIndexIntoMasterTable(COMMAND, UpdateCRTC_DoubleBufferRegisters);174 ENABLE_CRTC_PS_ALLOCATION args;175 176 memset(&args, 0, sizeof(args));177 178 args.ucCRTC = radeon_crtc->crtc_id;179 args.ucEnable = lock;180 181 atom_execute_table(rdev->mode_info.atom_context, index, (uint32_t *)&args, sizeof(args));182}183 184static void atombios_enable_crtc(struct drm_crtc *crtc, int state)185{186 struct radeon_crtc *radeon_crtc = to_radeon_crtc(crtc);187 struct drm_device *dev = crtc->dev;188 struct radeon_device *rdev = dev->dev_private;189 int index = GetIndexIntoMasterTable(COMMAND, EnableCRTC);190 ENABLE_CRTC_PS_ALLOCATION args;191 192 memset(&args, 0, sizeof(args));193 194 args.ucCRTC = radeon_crtc->crtc_id;195 args.ucEnable = state;196 197 atom_execute_table(rdev->mode_info.atom_context, index, (uint32_t *)&args, sizeof(args));198}199 200static void atombios_enable_crtc_memreq(struct drm_crtc *crtc, int state)201{202 struct radeon_crtc *radeon_crtc = to_radeon_crtc(crtc);203 struct drm_device *dev = crtc->dev;204 struct radeon_device *rdev = dev->dev_private;205 int index = GetIndexIntoMasterTable(COMMAND, EnableCRTCMemReq);206 ENABLE_CRTC_PS_ALLOCATION args;207 208 memset(&args, 0, sizeof(args));209 210 args.ucCRTC = radeon_crtc->crtc_id;211 args.ucEnable = state;212 213 atom_execute_table(rdev->mode_info.atom_context, index, (uint32_t *)&args, sizeof(args));214}215 216static const u32 vga_control_regs[6] =217{218 AVIVO_D1VGA_CONTROL,219 AVIVO_D2VGA_CONTROL,220 EVERGREEN_D3VGA_CONTROL,221 EVERGREEN_D4VGA_CONTROL,222 EVERGREEN_D5VGA_CONTROL,223 EVERGREEN_D6VGA_CONTROL,224};225 226static void atombios_blank_crtc(struct drm_crtc *crtc, int state)227{228 struct radeon_crtc *radeon_crtc = to_radeon_crtc(crtc);229 struct drm_device *dev = crtc->dev;230 struct radeon_device *rdev = dev->dev_private;231 int index = GetIndexIntoMasterTable(COMMAND, BlankCRTC);232 BLANK_CRTC_PS_ALLOCATION args;233 u32 vga_control = 0;234 235 memset(&args, 0, sizeof(args));236 237 if (ASIC_IS_DCE8(rdev)) {238 vga_control = RREG32(vga_control_regs[radeon_crtc->crtc_id]);239 WREG32(vga_control_regs[radeon_crtc->crtc_id], vga_control | 1);240 }241 242 args.ucCRTC = radeon_crtc->crtc_id;243 args.ucBlanking = state;244 245 atom_execute_table(rdev->mode_info.atom_context, index, (uint32_t *)&args, sizeof(args));246 247 if (ASIC_IS_DCE8(rdev))248 WREG32(vga_control_regs[radeon_crtc->crtc_id], vga_control);249}250 251static void atombios_powergate_crtc(struct drm_crtc *crtc, int state)252{253 struct radeon_crtc *radeon_crtc = to_radeon_crtc(crtc);254 struct drm_device *dev = crtc->dev;255 struct radeon_device *rdev = dev->dev_private;256 int index = GetIndexIntoMasterTable(COMMAND, EnableDispPowerGating);257 ENABLE_DISP_POWER_GATING_PARAMETERS_V2_1 args;258 259 memset(&args, 0, sizeof(args));260 261 args.ucDispPipeId = radeon_crtc->crtc_id;262 args.ucEnable = state;263 264 atom_execute_table(rdev->mode_info.atom_context, index, (uint32_t *)&args, sizeof(args));265}266 267void atombios_crtc_dpms(struct drm_crtc *crtc, int mode)268{269 struct drm_device *dev = crtc->dev;270 struct radeon_device *rdev = dev->dev_private;271 struct radeon_crtc *radeon_crtc = to_radeon_crtc(crtc);272 273 switch (mode) {274 case DRM_MODE_DPMS_ON:275 radeon_crtc->enabled = true;276 atombios_enable_crtc(crtc, ATOM_ENABLE);277 if (ASIC_IS_DCE3(rdev) && !ASIC_IS_DCE6(rdev))278 atombios_enable_crtc_memreq(crtc, ATOM_ENABLE);279 atombios_blank_crtc(crtc, ATOM_DISABLE);280 if (dev->num_crtcs > radeon_crtc->crtc_id)281 drm_crtc_vblank_on(crtc);282 radeon_crtc_load_lut(crtc);283 break;284 case DRM_MODE_DPMS_STANDBY:285 case DRM_MODE_DPMS_SUSPEND:286 case DRM_MODE_DPMS_OFF:287 if (dev->num_crtcs > radeon_crtc->crtc_id)288 drm_crtc_vblank_off(crtc);289 if (radeon_crtc->enabled)290 atombios_blank_crtc(crtc, ATOM_ENABLE);291 if (ASIC_IS_DCE3(rdev) && !ASIC_IS_DCE6(rdev))292 atombios_enable_crtc_memreq(crtc, ATOM_DISABLE);293 atombios_enable_crtc(crtc, ATOM_DISABLE);294 radeon_crtc->enabled = false;295 break;296 }297 /* adjust pm to dpms */298 radeon_pm_compute_clocks(rdev);299}300 301static void302atombios_set_crtc_dtd_timing(struct drm_crtc *crtc,303 struct drm_display_mode *mode)304{305 struct radeon_crtc *radeon_crtc = to_radeon_crtc(crtc);306 struct drm_device *dev = crtc->dev;307 struct radeon_device *rdev = dev->dev_private;308 SET_CRTC_USING_DTD_TIMING_PARAMETERS args;309 int index = GetIndexIntoMasterTable(COMMAND, SetCRTC_UsingDTDTiming);310 u16 misc = 0;311 312 memset(&args, 0, sizeof(args));313 args.usH_Size = cpu_to_le16(mode->crtc_hdisplay - (radeon_crtc->h_border * 2));314 args.usH_Blanking_Time =315 cpu_to_le16(mode->crtc_hblank_end - mode->crtc_hdisplay + (radeon_crtc->h_border * 2));316 args.usV_Size = cpu_to_le16(mode->crtc_vdisplay - (radeon_crtc->v_border * 2));317 args.usV_Blanking_Time =318 cpu_to_le16(mode->crtc_vblank_end - mode->crtc_vdisplay + (radeon_crtc->v_border * 2));319 args.usH_SyncOffset =320 cpu_to_le16(mode->crtc_hsync_start - mode->crtc_hdisplay + radeon_crtc->h_border);321 args.usH_SyncWidth =322 cpu_to_le16(mode->crtc_hsync_end - mode->crtc_hsync_start);323 args.usV_SyncOffset =324 cpu_to_le16(mode->crtc_vsync_start - mode->crtc_vdisplay + radeon_crtc->v_border);325 args.usV_SyncWidth =326 cpu_to_le16(mode->crtc_vsync_end - mode->crtc_vsync_start);327 args.ucH_Border = radeon_crtc->h_border;328 args.ucV_Border = radeon_crtc->v_border;329 330 if (mode->flags & DRM_MODE_FLAG_NVSYNC)331 misc |= ATOM_VSYNC_POLARITY;332 if (mode->flags & DRM_MODE_FLAG_NHSYNC)333 misc |= ATOM_HSYNC_POLARITY;334 if (mode->flags & DRM_MODE_FLAG_CSYNC)335 misc |= ATOM_COMPOSITESYNC;336 if (mode->flags & DRM_MODE_FLAG_INTERLACE)337 misc |= ATOM_INTERLACE;338 if (mode->flags & DRM_MODE_FLAG_DBLCLK)339 misc |= ATOM_DOUBLE_CLOCK_MODE;340 if (mode->flags & DRM_MODE_FLAG_DBLSCAN)341 misc |= ATOM_H_REPLICATIONBY2 | ATOM_V_REPLICATIONBY2;342 343 args.susModeMiscInfo.usAccess = cpu_to_le16(misc);344 args.ucCRTC = radeon_crtc->crtc_id;345 346 atom_execute_table(rdev->mode_info.atom_context, index, (uint32_t *)&args, sizeof(args));347}348 349static void atombios_crtc_set_timing(struct drm_crtc *crtc,350 struct drm_display_mode *mode)351{352 struct radeon_crtc *radeon_crtc = to_radeon_crtc(crtc);353 struct drm_device *dev = crtc->dev;354 struct radeon_device *rdev = dev->dev_private;355 SET_CRTC_TIMING_PARAMETERS_PS_ALLOCATION args;356 int index = GetIndexIntoMasterTable(COMMAND, SetCRTC_Timing);357 u16 misc = 0;358 359 memset(&args, 0, sizeof(args));360 args.usH_Total = cpu_to_le16(mode->crtc_htotal);361 args.usH_Disp = cpu_to_le16(mode->crtc_hdisplay);362 args.usH_SyncStart = cpu_to_le16(mode->crtc_hsync_start);363 args.usH_SyncWidth =364 cpu_to_le16(mode->crtc_hsync_end - mode->crtc_hsync_start);365 args.usV_Total = cpu_to_le16(mode->crtc_vtotal);366 args.usV_Disp = cpu_to_le16(mode->crtc_vdisplay);367 args.usV_SyncStart = cpu_to_le16(mode->crtc_vsync_start);368 args.usV_SyncWidth =369 cpu_to_le16(mode->crtc_vsync_end - mode->crtc_vsync_start);370 371 args.ucOverscanRight = radeon_crtc->h_border;372 args.ucOverscanLeft = radeon_crtc->h_border;373 args.ucOverscanBottom = radeon_crtc->v_border;374 args.ucOverscanTop = radeon_crtc->v_border;375 376 if (mode->flags & DRM_MODE_FLAG_NVSYNC)377 misc |= ATOM_VSYNC_POLARITY;378 if (mode->flags & DRM_MODE_FLAG_NHSYNC)379 misc |= ATOM_HSYNC_POLARITY;380 if (mode->flags & DRM_MODE_FLAG_CSYNC)381 misc |= ATOM_COMPOSITESYNC;382 if (mode->flags & DRM_MODE_FLAG_INTERLACE)383 misc |= ATOM_INTERLACE;384 if (mode->flags & DRM_MODE_FLAG_DBLCLK)385 misc |= ATOM_DOUBLE_CLOCK_MODE;386 if (mode->flags & DRM_MODE_FLAG_DBLSCAN)387 misc |= ATOM_H_REPLICATIONBY2 | ATOM_V_REPLICATIONBY2;388 389 args.susModeMiscInfo.usAccess = cpu_to_le16(misc);390 args.ucCRTC = radeon_crtc->crtc_id;391 392 atom_execute_table(rdev->mode_info.atom_context, index, (uint32_t *)&args, sizeof(args));393}394 395static void atombios_disable_ss(struct radeon_device *rdev, int pll_id)396{397 u32 ss_cntl;398 399 if (ASIC_IS_DCE4(rdev)) {400 switch (pll_id) {401 case ATOM_PPLL1:402 ss_cntl = RREG32(EVERGREEN_P1PLL_SS_CNTL);403 ss_cntl &= ~EVERGREEN_PxPLL_SS_EN;404 WREG32(EVERGREEN_P1PLL_SS_CNTL, ss_cntl);405 break;406 case ATOM_PPLL2:407 ss_cntl = RREG32(EVERGREEN_P2PLL_SS_CNTL);408 ss_cntl &= ~EVERGREEN_PxPLL_SS_EN;409 WREG32(EVERGREEN_P2PLL_SS_CNTL, ss_cntl);410 break;411 case ATOM_DCPLL:412 case ATOM_PPLL_INVALID:413 return;414 }415 } else if (ASIC_IS_AVIVO(rdev)) {416 switch (pll_id) {417 case ATOM_PPLL1:418 ss_cntl = RREG32(AVIVO_P1PLL_INT_SS_CNTL);419 ss_cntl &= ~1;420 WREG32(AVIVO_P1PLL_INT_SS_CNTL, ss_cntl);421 break;422 case ATOM_PPLL2:423 ss_cntl = RREG32(AVIVO_P2PLL_INT_SS_CNTL);424 ss_cntl &= ~1;425 WREG32(AVIVO_P2PLL_INT_SS_CNTL, ss_cntl);426 break;427 case ATOM_DCPLL:428 case ATOM_PPLL_INVALID:429 return;430 }431 }432}433 434 435union atom_enable_ss {436 ENABLE_LVDS_SS_PARAMETERS lvds_ss;437 ENABLE_LVDS_SS_PARAMETERS_V2 lvds_ss_2;438 ENABLE_SPREAD_SPECTRUM_ON_PPLL_PS_ALLOCATION v1;439 ENABLE_SPREAD_SPECTRUM_ON_PPLL_V2 v2;440 ENABLE_SPREAD_SPECTRUM_ON_PPLL_V3 v3;441};442 443static void atombios_crtc_program_ss(struct radeon_device *rdev,444 int enable,445 int pll_id,446 int crtc_id,447 struct radeon_atom_ss *ss)448{449 unsigned i;450 int index = GetIndexIntoMasterTable(COMMAND, EnableSpreadSpectrumOnPPLL);451 union atom_enable_ss args;452 453 if (enable) {454 /* Don't mess with SS if percentage is 0 or external ss.455 * SS is already disabled previously, and disabling it456 * again can cause display problems if the pll is already457 * programmed.458 */459 if (ss->percentage == 0)460 return;461 if (ss->type & ATOM_EXTERNAL_SS_MASK)462 return;463 } else {464 for (i = 0; i < rdev->num_crtc; i++) {465 if (rdev->mode_info.crtcs[i] &&466 rdev->mode_info.crtcs[i]->enabled &&467 i != crtc_id &&468 pll_id == rdev->mode_info.crtcs[i]->pll_id) {469 /* one other crtc is using this pll don't turn470 * off spread spectrum as it might turn off471 * display on active crtc472 */473 return;474 }475 }476 }477 478 memset(&args, 0, sizeof(args));479 480 if (ASIC_IS_DCE5(rdev)) {481 args.v3.usSpreadSpectrumAmountFrac = cpu_to_le16(0);482 args.v3.ucSpreadSpectrumType = ss->type & ATOM_SS_CENTRE_SPREAD_MODE_MASK;483 switch (pll_id) {484 case ATOM_PPLL1:485 args.v3.ucSpreadSpectrumType |= ATOM_PPLL_SS_TYPE_V3_P1PLL;486 break;487 case ATOM_PPLL2:488 args.v3.ucSpreadSpectrumType |= ATOM_PPLL_SS_TYPE_V3_P2PLL;489 break;490 case ATOM_DCPLL:491 args.v3.ucSpreadSpectrumType |= ATOM_PPLL_SS_TYPE_V3_DCPLL;492 break;493 case ATOM_PPLL_INVALID:494 return;495 }496 args.v3.usSpreadSpectrumAmount = cpu_to_le16(ss->amount);497 args.v3.usSpreadSpectrumStep = cpu_to_le16(ss->step);498 args.v3.ucEnable = enable;499 } else if (ASIC_IS_DCE4(rdev)) {500 args.v2.usSpreadSpectrumPercentage = cpu_to_le16(ss->percentage);501 args.v2.ucSpreadSpectrumType = ss->type & ATOM_SS_CENTRE_SPREAD_MODE_MASK;502 switch (pll_id) {503 case ATOM_PPLL1:504 args.v2.ucSpreadSpectrumType |= ATOM_PPLL_SS_TYPE_V2_P1PLL;505 break;506 case ATOM_PPLL2:507 args.v2.ucSpreadSpectrumType |= ATOM_PPLL_SS_TYPE_V2_P2PLL;508 break;509 case ATOM_DCPLL:510 args.v2.ucSpreadSpectrumType |= ATOM_PPLL_SS_TYPE_V2_DCPLL;511 break;512 case ATOM_PPLL_INVALID:513 return;514 }515 args.v2.usSpreadSpectrumAmount = cpu_to_le16(ss->amount);516 args.v2.usSpreadSpectrumStep = cpu_to_le16(ss->step);517 args.v2.ucEnable = enable;518 } else if (ASIC_IS_DCE3(rdev)) {519 args.v1.usSpreadSpectrumPercentage = cpu_to_le16(ss->percentage);520 args.v1.ucSpreadSpectrumType = ss->type & ATOM_SS_CENTRE_SPREAD_MODE_MASK;521 args.v1.ucSpreadSpectrumStep = ss->step;522 args.v1.ucSpreadSpectrumDelay = ss->delay;523 args.v1.ucSpreadSpectrumRange = ss->range;524 args.v1.ucPpll = pll_id;525 args.v1.ucEnable = enable;526 } else if (ASIC_IS_AVIVO(rdev)) {527 if ((enable == ATOM_DISABLE) || (ss->percentage == 0) ||528 (ss->type & ATOM_EXTERNAL_SS_MASK)) {529 atombios_disable_ss(rdev, pll_id);530 return;531 }532 args.lvds_ss_2.usSpreadSpectrumPercentage = cpu_to_le16(ss->percentage);533 args.lvds_ss_2.ucSpreadSpectrumType = ss->type & ATOM_SS_CENTRE_SPREAD_MODE_MASK;534 args.lvds_ss_2.ucSpreadSpectrumStep = ss->step;535 args.lvds_ss_2.ucSpreadSpectrumDelay = ss->delay;536 args.lvds_ss_2.ucSpreadSpectrumRange = ss->range;537 args.lvds_ss_2.ucEnable = enable;538 } else {539 if (enable == ATOM_DISABLE) {540 atombios_disable_ss(rdev, pll_id);541 return;542 }543 args.lvds_ss.usSpreadSpectrumPercentage = cpu_to_le16(ss->percentage);544 args.lvds_ss.ucSpreadSpectrumType = ss->type & ATOM_SS_CENTRE_SPREAD_MODE_MASK;545 args.lvds_ss.ucSpreadSpectrumStepSize_Delay = (ss->step & 3) << 2;546 args.lvds_ss.ucSpreadSpectrumStepSize_Delay |= (ss->delay & 7) << 4;547 args.lvds_ss.ucEnable = enable;548 }549 atom_execute_table(rdev->mode_info.atom_context, index, (uint32_t *)&args, sizeof(args));550}551 552union adjust_pixel_clock {553 ADJUST_DISPLAY_PLL_PS_ALLOCATION v1;554 ADJUST_DISPLAY_PLL_PS_ALLOCATION_V3 v3;555};556 557static u32 atombios_adjust_pll(struct drm_crtc *crtc,558 struct drm_display_mode *mode)559{560 struct radeon_crtc *radeon_crtc = to_radeon_crtc(crtc);561 struct drm_device *dev = crtc->dev;562 struct radeon_device *rdev = dev->dev_private;563 struct drm_encoder *encoder = radeon_crtc->encoder;564 struct radeon_encoder *radeon_encoder = to_radeon_encoder(encoder);565 struct drm_connector *connector = radeon_get_connector_for_encoder(encoder);566 u32 adjusted_clock = mode->clock;567 int encoder_mode = atombios_get_encoder_mode(encoder);568 u32 dp_clock = mode->clock;569 u32 clock = mode->clock;570 int bpc = radeon_crtc->bpc;571 bool is_duallink = radeon_dig_monitor_is_duallink(encoder, mode->clock);572 573 /* reset the pll flags */574 radeon_crtc->pll_flags = 0;575 576 if (ASIC_IS_AVIVO(rdev)) {577 if ((rdev->family == CHIP_RS600) ||578 (rdev->family == CHIP_RS690) ||579 (rdev->family == CHIP_RS740))580 radeon_crtc->pll_flags |= (/*RADEON_PLL_USE_FRAC_FB_DIV |*/581 RADEON_PLL_PREFER_CLOSEST_LOWER);582 583 if (ASIC_IS_DCE32(rdev) && mode->clock > 200000) /* range limits??? */584 radeon_crtc->pll_flags |= RADEON_PLL_PREFER_HIGH_FB_DIV;585 else586 radeon_crtc->pll_flags |= RADEON_PLL_PREFER_LOW_REF_DIV;587 588 if (rdev->family < CHIP_RV770)589 radeon_crtc->pll_flags |= RADEON_PLL_PREFER_MINM_OVER_MAXP;590 /* use frac fb div on APUs */591 if (ASIC_IS_DCE41(rdev) || ASIC_IS_DCE61(rdev) || ASIC_IS_DCE8(rdev))592 radeon_crtc->pll_flags |= RADEON_PLL_USE_FRAC_FB_DIV;593 /* use frac fb div on RS780/RS880 */594 if (((rdev->family == CHIP_RS780) || (rdev->family == CHIP_RS880))595 && !radeon_crtc->ss_enabled)596 radeon_crtc->pll_flags |= RADEON_PLL_USE_FRAC_FB_DIV;597 if (ASIC_IS_DCE32(rdev) && mode->clock > 165000)598 radeon_crtc->pll_flags |= RADEON_PLL_USE_FRAC_FB_DIV;599 } else {600 radeon_crtc->pll_flags |= RADEON_PLL_LEGACY;601 602 if (mode->clock > 200000) /* range limits??? */603 radeon_crtc->pll_flags |= RADEON_PLL_PREFER_HIGH_FB_DIV;604 else605 radeon_crtc->pll_flags |= RADEON_PLL_PREFER_LOW_REF_DIV;606 }607 608 if ((radeon_encoder->devices & (ATOM_DEVICE_LCD_SUPPORT | ATOM_DEVICE_DFP_SUPPORT)) ||609 (radeon_encoder_get_dp_bridge_encoder_id(encoder) != ENCODER_OBJECT_ID_NONE)) {610 if (connector) {611 struct radeon_connector *radeon_connector = to_radeon_connector(connector);612 struct radeon_connector_atom_dig *dig_connector =613 radeon_connector->con_priv;614 615 dp_clock = dig_connector->dp_clock;616 }617 }618 619 /* use recommended ref_div for ss */620 if (radeon_encoder->devices & (ATOM_DEVICE_LCD_SUPPORT)) {621 if (radeon_crtc->ss_enabled) {622 if (radeon_crtc->ss.refdiv) {623 radeon_crtc->pll_flags |= RADEON_PLL_USE_REF_DIV;624 radeon_crtc->pll_reference_div = radeon_crtc->ss.refdiv;625 if (ASIC_IS_AVIVO(rdev) &&626 rdev->family != CHIP_RS780 &&627 rdev->family != CHIP_RS880)628 radeon_crtc->pll_flags |= RADEON_PLL_USE_FRAC_FB_DIV;629 }630 }631 }632 633 if (ASIC_IS_AVIVO(rdev)) {634 /* DVO wants 2x pixel clock if the DVO chip is in 12 bit mode */635 if (radeon_encoder->encoder_id == ENCODER_OBJECT_ID_INTERNAL_KLDSCP_DVO1)636 adjusted_clock = mode->clock * 2;637 if (radeon_encoder->active_device & (ATOM_DEVICE_TV_SUPPORT))638 radeon_crtc->pll_flags |= RADEON_PLL_PREFER_CLOSEST_LOWER;639 if (radeon_encoder->devices & (ATOM_DEVICE_LCD_SUPPORT))640 radeon_crtc->pll_flags |= RADEON_PLL_IS_LCD;641 } else {642 if (encoder->encoder_type != DRM_MODE_ENCODER_DAC)643 radeon_crtc->pll_flags |= RADEON_PLL_NO_ODD_POST_DIV;644 if (encoder->encoder_type == DRM_MODE_ENCODER_LVDS)645 radeon_crtc->pll_flags |= RADEON_PLL_USE_REF_DIV;646 }647 648 /* adjust pll for deep color modes */649 if (encoder_mode == ATOM_ENCODER_MODE_HDMI) {650 switch (bpc) {651 case 8:652 default:653 break;654 case 10:655 clock = (clock * 5) / 4;656 break;657 case 12:658 clock = (clock * 3) / 2;659 break;660 case 16:661 clock = clock * 2;662 break;663 }664 }665 666 /* DCE3+ has an AdjustDisplayPll that will adjust the pixel clock667 * accordingly based on the encoder/transmitter to work around668 * special hw requirements.669 */670 if (ASIC_IS_DCE3(rdev)) {671 union adjust_pixel_clock args;672 u8 frev, crev;673 int index;674 675 index = GetIndexIntoMasterTable(COMMAND, AdjustDisplayPll);676 if (!atom_parse_cmd_header(rdev->mode_info.atom_context, index, &frev,677 &crev))678 return adjusted_clock;679 680 memset(&args, 0, sizeof(args));681 682 switch (frev) {683 case 1:684 switch (crev) {685 case 1:686 case 2:687 args.v1.usPixelClock = cpu_to_le16(clock / 10);688 args.v1.ucTransmitterID = radeon_encoder->encoder_id;689 args.v1.ucEncodeMode = encoder_mode;690 if (radeon_crtc->ss_enabled && radeon_crtc->ss.percentage)691 args.v1.ucConfig |=692 ADJUST_DISPLAY_CONFIG_SS_ENABLE;693 694 atom_execute_table(rdev->mode_info.atom_context,695 index, (uint32_t *)&args, sizeof(args));696 adjusted_clock = le16_to_cpu(args.v1.usPixelClock) * 10;697 break;698 case 3:699 args.v3.sInput.usPixelClock = cpu_to_le16(clock / 10);700 args.v3.sInput.ucTransmitterID = radeon_encoder->encoder_id;701 args.v3.sInput.ucEncodeMode = encoder_mode;702 args.v3.sInput.ucDispPllConfig = 0;703 if (radeon_crtc->ss_enabled && radeon_crtc->ss.percentage)704 args.v3.sInput.ucDispPllConfig |=705 DISPPLL_CONFIG_SS_ENABLE;706 if (ENCODER_MODE_IS_DP(encoder_mode)) {707 args.v3.sInput.ucDispPllConfig |=708 DISPPLL_CONFIG_COHERENT_MODE;709 /* 16200 or 27000 */710 args.v3.sInput.usPixelClock = cpu_to_le16(dp_clock / 10);711 } else if (radeon_encoder->devices & (ATOM_DEVICE_DFP_SUPPORT)) {712 struct radeon_encoder_atom_dig *dig = radeon_encoder->enc_priv;713 if (dig->coherent_mode)714 args.v3.sInput.ucDispPllConfig |=715 DISPPLL_CONFIG_COHERENT_MODE;716 if (is_duallink)717 args.v3.sInput.ucDispPllConfig |=718 DISPPLL_CONFIG_DUAL_LINK;719 }720 if (radeon_encoder_get_dp_bridge_encoder_id(encoder) !=721 ENCODER_OBJECT_ID_NONE)722 args.v3.sInput.ucExtTransmitterID =723 radeon_encoder_get_dp_bridge_encoder_id(encoder);724 else725 args.v3.sInput.ucExtTransmitterID = 0;726 727 atom_execute_table(rdev->mode_info.atom_context,728 index, (uint32_t *)&args, sizeof(args));729 adjusted_clock = le32_to_cpu(args.v3.sOutput.ulDispPllFreq) * 10;730 if (args.v3.sOutput.ucRefDiv) {731 radeon_crtc->pll_flags |= RADEON_PLL_USE_FRAC_FB_DIV;732 radeon_crtc->pll_flags |= RADEON_PLL_USE_REF_DIV;733 radeon_crtc->pll_reference_div = args.v3.sOutput.ucRefDiv;734 }735 if (args.v3.sOutput.ucPostDiv) {736 radeon_crtc->pll_flags |= RADEON_PLL_USE_FRAC_FB_DIV;737 radeon_crtc->pll_flags |= RADEON_PLL_USE_POST_DIV;738 radeon_crtc->pll_post_div = args.v3.sOutput.ucPostDiv;739 }740 break;741 default:742 DRM_ERROR("Unknown table version %d %d\n", frev, crev);743 return adjusted_clock;744 }745 break;746 default:747 DRM_ERROR("Unknown table version %d %d\n", frev, crev);748 return adjusted_clock;749 }750 }751 return adjusted_clock;752}753 754union set_pixel_clock {755 SET_PIXEL_CLOCK_PS_ALLOCATION base;756 PIXEL_CLOCK_PARAMETERS v1;757 PIXEL_CLOCK_PARAMETERS_V2 v2;758 PIXEL_CLOCK_PARAMETERS_V3 v3;759 PIXEL_CLOCK_PARAMETERS_V5 v5;760 PIXEL_CLOCK_PARAMETERS_V6 v6;761};762 763/* on DCE5, make sure the voltage is high enough to support the764 * required disp clk.765 */766static void atombios_crtc_set_disp_eng_pll(struct radeon_device *rdev,767 u32 dispclk)768{769 u8 frev, crev;770 int index;771 union set_pixel_clock args;772 773 memset(&args, 0, sizeof(args));774 775 index = GetIndexIntoMasterTable(COMMAND, SetPixelClock);776 if (!atom_parse_cmd_header(rdev->mode_info.atom_context, index, &frev,777 &crev))778 return;779 780 switch (frev) {781 case 1:782 switch (crev) {783 case 5:784 /* if the default dcpll clock is specified,785 * SetPixelClock provides the dividers786 */787 args.v5.ucCRTC = ATOM_CRTC_INVALID;788 args.v5.usPixelClock = cpu_to_le16(dispclk);789 args.v5.ucPpll = ATOM_DCPLL;790 break;791 case 6:792 /* if the default dcpll clock is specified,793 * SetPixelClock provides the dividers794 */795 args.v6.ulDispEngClkFreq = cpu_to_le32(dispclk);796 if (ASIC_IS_DCE61(rdev) || ASIC_IS_DCE8(rdev))797 args.v6.ucPpll = ATOM_EXT_PLL1;798 else if (ASIC_IS_DCE6(rdev))799 args.v6.ucPpll = ATOM_PPLL0;800 else801 args.v6.ucPpll = ATOM_DCPLL;802 break;803 default:804 DRM_ERROR("Unknown table version %d %d\n", frev, crev);805 return;806 }807 break;808 default:809 DRM_ERROR("Unknown table version %d %d\n", frev, crev);810 return;811 }812 atom_execute_table(rdev->mode_info.atom_context, index, (uint32_t *)&args, sizeof(args));813}814 815static void atombios_crtc_program_pll(struct drm_crtc *crtc,816 u32 crtc_id,817 int pll_id,818 u32 encoder_mode,819 u32 encoder_id,820 u32 clock,821 u32 ref_div,822 u32 fb_div,823 u32 frac_fb_div,824 u32 post_div,825 int bpc,826 bool ss_enabled,827 struct radeon_atom_ss *ss)828{829 struct drm_device *dev = crtc->dev;830 struct radeon_device *rdev = dev->dev_private;831 u8 frev, crev;832 int index = GetIndexIntoMasterTable(COMMAND, SetPixelClock);833 union set_pixel_clock args;834 835 memset(&args, 0, sizeof(args));836 837 if (!atom_parse_cmd_header(rdev->mode_info.atom_context, index, &frev,838 &crev))839 return;840 841 switch (frev) {842 case 1:843 switch (crev) {844 case 1:845 if (clock == ATOM_DISABLE)846 return;847 args.v1.usPixelClock = cpu_to_le16(clock / 10);848 args.v1.usRefDiv = cpu_to_le16(ref_div);849 args.v1.usFbDiv = cpu_to_le16(fb_div);850 args.v1.ucFracFbDiv = frac_fb_div;851 args.v1.ucPostDiv = post_div;852 args.v1.ucPpll = pll_id;853 args.v1.ucCRTC = crtc_id;854 args.v1.ucRefDivSrc = 1;855 break;856 case 2:857 args.v2.usPixelClock = cpu_to_le16(clock / 10);858 args.v2.usRefDiv = cpu_to_le16(ref_div);859 args.v2.usFbDiv = cpu_to_le16(fb_div);860 args.v2.ucFracFbDiv = frac_fb_div;861 args.v2.ucPostDiv = post_div;862 args.v2.ucPpll = pll_id;863 args.v2.ucCRTC = crtc_id;864 args.v2.ucRefDivSrc = 1;865 break;866 case 3:867 args.v3.usPixelClock = cpu_to_le16(clock / 10);868 args.v3.usRefDiv = cpu_to_le16(ref_div);869 args.v3.usFbDiv = cpu_to_le16(fb_div);870 args.v3.ucFracFbDiv = frac_fb_div;871 args.v3.ucPostDiv = post_div;872 args.v3.ucPpll = pll_id;873 if (crtc_id == ATOM_CRTC2)874 args.v3.ucMiscInfo = PIXEL_CLOCK_MISC_CRTC_SEL_CRTC2;875 else876 args.v3.ucMiscInfo = PIXEL_CLOCK_MISC_CRTC_SEL_CRTC1;877 if (ss_enabled && (ss->type & ATOM_EXTERNAL_SS_MASK))878 args.v3.ucMiscInfo |= PIXEL_CLOCK_MISC_REF_DIV_SRC;879 args.v3.ucTransmitterId = encoder_id;880 args.v3.ucEncoderMode = encoder_mode;881 break;882 case 5:883 args.v5.ucCRTC = crtc_id;884 args.v5.usPixelClock = cpu_to_le16(clock / 10);885 args.v5.ucRefDiv = ref_div;886 args.v5.usFbDiv = cpu_to_le16(fb_div);887 args.v5.ulFbDivDecFrac = cpu_to_le32(frac_fb_div * 100000);888 args.v5.ucPostDiv = post_div;889 args.v5.ucMiscInfo = 0; /* HDMI depth, etc. */890 if (ss_enabled && (ss->type & ATOM_EXTERNAL_SS_MASK))891 args.v5.ucMiscInfo |= PIXEL_CLOCK_V5_MISC_REF_DIV_SRC;892 if (encoder_mode == ATOM_ENCODER_MODE_HDMI) {893 switch (bpc) {894 case 8:895 default:896 args.v5.ucMiscInfo |= PIXEL_CLOCK_V5_MISC_HDMI_24BPP;897 break;898 case 10:899 /* yes this is correct, the atom define is wrong */900 args.v5.ucMiscInfo |= PIXEL_CLOCK_V5_MISC_HDMI_32BPP;901 break;902 case 12:903 /* yes this is correct, the atom define is wrong */904 args.v5.ucMiscInfo |= PIXEL_CLOCK_V5_MISC_HDMI_30BPP;905 break;906 }907 }908 args.v5.ucTransmitterID = encoder_id;909 args.v5.ucEncoderMode = encoder_mode;910 args.v5.ucPpll = pll_id;911 break;912 case 6:913 args.v6.ulDispEngClkFreq = cpu_to_le32(crtc_id << 24 | clock / 10);914 args.v6.ucRefDiv = ref_div;915 args.v6.usFbDiv = cpu_to_le16(fb_div);916 args.v6.ulFbDivDecFrac = cpu_to_le32(frac_fb_div * 100000);917 args.v6.ucPostDiv = post_div;918 args.v6.ucMiscInfo = 0; /* HDMI depth, etc. */919 if (ss_enabled && (ss->type & ATOM_EXTERNAL_SS_MASK))920 args.v6.ucMiscInfo |= PIXEL_CLOCK_V6_MISC_REF_DIV_SRC;921 if (encoder_mode == ATOM_ENCODER_MODE_HDMI) {922 switch (bpc) {923 case 8:924 default:925 args.v6.ucMiscInfo |= PIXEL_CLOCK_V6_MISC_HDMI_24BPP;926 break;927 case 10:928 args.v6.ucMiscInfo |= PIXEL_CLOCK_V6_MISC_HDMI_30BPP_V6;929 break;930 case 12:931 args.v6.ucMiscInfo |= PIXEL_CLOCK_V6_MISC_HDMI_36BPP_V6;932 break;933 case 16:934 args.v6.ucMiscInfo |= PIXEL_CLOCK_V6_MISC_HDMI_48BPP;935 break;936 }937 }938 args.v6.ucTransmitterID = encoder_id;939 args.v6.ucEncoderMode = encoder_mode;940 args.v6.ucPpll = pll_id;941 break;942 default:943 DRM_ERROR("Unknown table version %d %d\n", frev, crev);944 return;945 }946 break;947 default:948 DRM_ERROR("Unknown table version %d %d\n", frev, crev);949 return;950 }951 952 atom_execute_table(rdev->mode_info.atom_context, index, (uint32_t *)&args, sizeof(args));953}954 955static bool atombios_crtc_prepare_pll(struct drm_crtc *crtc, struct drm_display_mode *mode)956{957 struct radeon_crtc *radeon_crtc = to_radeon_crtc(crtc);958 struct drm_device *dev = crtc->dev;959 struct radeon_device *rdev = dev->dev_private;960 struct radeon_encoder *radeon_encoder =961 to_radeon_encoder(radeon_crtc->encoder);962 int encoder_mode = atombios_get_encoder_mode(radeon_crtc->encoder);963 964 radeon_crtc->bpc = 8;965 radeon_crtc->ss_enabled = false;966 967 if ((radeon_encoder->active_device & (ATOM_DEVICE_LCD_SUPPORT | ATOM_DEVICE_DFP_SUPPORT)) ||968 (radeon_encoder_get_dp_bridge_encoder_id(radeon_crtc->encoder) != ENCODER_OBJECT_ID_NONE)) {969 struct radeon_encoder_atom_dig *dig = radeon_encoder->enc_priv;970 struct drm_connector *connector =971 radeon_get_connector_for_encoder(radeon_crtc->encoder);972 struct radeon_connector *radeon_connector =973 to_radeon_connector(connector);974 struct radeon_connector_atom_dig *dig_connector =975 radeon_connector->con_priv;976 int dp_clock;977 978 /* Assign mode clock for hdmi deep color max clock limit check */979 radeon_connector->pixelclock_for_modeset = mode->clock;980 radeon_crtc->bpc = radeon_get_monitor_bpc(connector);981 982 switch (encoder_mode) {983 case ATOM_ENCODER_MODE_DP_MST:984 case ATOM_ENCODER_MODE_DP:985 /* DP/eDP */986 dp_clock = dig_connector->dp_clock / 10;987 if (ASIC_IS_DCE4(rdev))988 radeon_crtc->ss_enabled =989 radeon_atombios_get_asic_ss_info(rdev, &radeon_crtc->ss,990 ASIC_INTERNAL_SS_ON_DP,991 dp_clock);992 else {993 if (dp_clock == 16200) {994 radeon_crtc->ss_enabled =995 radeon_atombios_get_ppll_ss_info(rdev,996 &radeon_crtc->ss,997 ATOM_DP_SS_ID2);998 if (!radeon_crtc->ss_enabled)999 radeon_crtc->ss_enabled =1000 radeon_atombios_get_ppll_ss_info(rdev,1001 &radeon_crtc->ss,1002 ATOM_DP_SS_ID1);1003 } else {1004 radeon_crtc->ss_enabled =1005 radeon_atombios_get_ppll_ss_info(rdev,1006 &radeon_crtc->ss,1007 ATOM_DP_SS_ID1);1008 }1009 /* disable spread spectrum on DCE3 DP */1010 radeon_crtc->ss_enabled = false;1011 }1012 break;1013 case ATOM_ENCODER_MODE_LVDS:1014 if (ASIC_IS_DCE4(rdev))1015 radeon_crtc->ss_enabled =1016 radeon_atombios_get_asic_ss_info(rdev,1017 &radeon_crtc->ss,1018 dig->lcd_ss_id,1019 mode->clock / 10);1020 else1021 radeon_crtc->ss_enabled =1022 radeon_atombios_get_ppll_ss_info(rdev,1023 &radeon_crtc->ss,1024 dig->lcd_ss_id);1025 break;1026 case ATOM_ENCODER_MODE_DVI:1027 if (ASIC_IS_DCE4(rdev))1028 radeon_crtc->ss_enabled =1029 radeon_atombios_get_asic_ss_info(rdev,1030 &radeon_crtc->ss,1031 ASIC_INTERNAL_SS_ON_TMDS,1032 mode->clock / 10);1033 break;1034 case ATOM_ENCODER_MODE_HDMI:1035 if (ASIC_IS_DCE4(rdev))1036 radeon_crtc->ss_enabled =1037 radeon_atombios_get_asic_ss_info(rdev,1038 &radeon_crtc->ss,1039 ASIC_INTERNAL_SS_ON_HDMI,1040 mode->clock / 10);1041 break;1042 default:1043 break;1044 }1045 }1046 1047 /* adjust pixel clock as needed */1048 radeon_crtc->adjusted_clock = atombios_adjust_pll(crtc, mode);1049 1050 return true;1051}1052 1053static void atombios_crtc_set_pll(struct drm_crtc *crtc, struct drm_display_mode *mode)1054{1055 struct radeon_crtc *radeon_crtc = to_radeon_crtc(crtc);1056 struct drm_device *dev = crtc->dev;1057 struct radeon_device *rdev = dev->dev_private;1058 struct radeon_encoder *radeon_encoder =1059 to_radeon_encoder(radeon_crtc->encoder);1060 u32 pll_clock = mode->clock;1061 u32 clock = mode->clock;1062 u32 ref_div = 0, fb_div = 0, frac_fb_div = 0, post_div = 0;1063 struct radeon_pll *pll;1064 int encoder_mode = atombios_get_encoder_mode(radeon_crtc->encoder);1065 1066 /* pass the actual clock to atombios_crtc_program_pll for DCE5,6 for HDMI */1067 if (ASIC_IS_DCE5(rdev) &&1068 (encoder_mode == ATOM_ENCODER_MODE_HDMI) &&1069 (radeon_crtc->bpc > 8))1070 clock = radeon_crtc->adjusted_clock;1071 1072 switch (radeon_crtc->pll_id) {1073 case ATOM_PPLL1:1074 pll = &rdev->clock.p1pll;1075 break;1076 case ATOM_PPLL2:1077 pll = &rdev->clock.p2pll;1078 break;1079 case ATOM_DCPLL:1080 case ATOM_PPLL_INVALID:1081 default:1082 pll = &rdev->clock.dcpll;1083 break;1084 }1085 1086 /* update pll params */1087 pll->flags = radeon_crtc->pll_flags;1088 pll->reference_div = radeon_crtc->pll_reference_div;1089 pll->post_div = radeon_crtc->pll_post_div;1090 1091 if (radeon_encoder->active_device & (ATOM_DEVICE_TV_SUPPORT))1092 /* TV seems to prefer the legacy algo on some boards */1093 radeon_compute_pll_legacy(pll, radeon_crtc->adjusted_clock, &pll_clock,1094 &fb_div, &frac_fb_div, &ref_div, &post_div);1095 else if (ASIC_IS_AVIVO(rdev))1096 radeon_compute_pll_avivo(pll, radeon_crtc->adjusted_clock, &pll_clock,1097 &fb_div, &frac_fb_div, &ref_div, &post_div);1098 else1099 radeon_compute_pll_legacy(pll, radeon_crtc->adjusted_clock, &pll_clock,1100 &fb_div, &frac_fb_div, &ref_div, &post_div);1101 1102 atombios_crtc_program_ss(rdev, ATOM_DISABLE, radeon_crtc->pll_id,1103 radeon_crtc->crtc_id, &radeon_crtc->ss);1104 1105 atombios_crtc_program_pll(crtc, radeon_crtc->crtc_id, radeon_crtc->pll_id,1106 encoder_mode, radeon_encoder->encoder_id, clock,1107 ref_div, fb_div, frac_fb_div, post_div,1108 radeon_crtc->bpc, radeon_crtc->ss_enabled, &radeon_crtc->ss);1109 1110 if (radeon_crtc->ss_enabled) {1111 /* calculate ss amount and step size */1112 if (ASIC_IS_DCE4(rdev)) {1113 u32 step_size;1114 u32 amount = (((fb_div * 10) + frac_fb_div) *1115 (u32)radeon_crtc->ss.percentage) /1116 (100 * (u32)radeon_crtc->ss.percentage_divider);1117 radeon_crtc->ss.amount = (amount / 10) & ATOM_PPLL_SS_AMOUNT_V2_FBDIV_MASK;1118 radeon_crtc->ss.amount |= ((amount - (amount / 10)) << ATOM_PPLL_SS_AMOUNT_V2_NFRAC_SHIFT) &1119 ATOM_PPLL_SS_AMOUNT_V2_NFRAC_MASK;1120 if (radeon_crtc->ss.type & ATOM_PPLL_SS_TYPE_V2_CENTRE_SPREAD)1121 step_size = (4 * amount * ref_div * ((u32)radeon_crtc->ss.rate * 2048)) /1122 (125 * 25 * pll->reference_freq / 100);1123 else1124 step_size = (2 * amount * ref_div * ((u32)radeon_crtc->ss.rate * 2048)) /1125 (125 * 25 * pll->reference_freq / 100);1126 radeon_crtc->ss.step = step_size;1127 }1128 1129 atombios_crtc_program_ss(rdev, ATOM_ENABLE, radeon_crtc->pll_id,1130 radeon_crtc->crtc_id, &radeon_crtc->ss);1131 }1132}1133 1134static int dce4_crtc_do_set_base(struct drm_crtc *crtc,1135 struct drm_framebuffer *fb,1136 int x, int y, int atomic)1137{1138 struct radeon_crtc *radeon_crtc = to_radeon_crtc(crtc);1139 struct drm_device *dev = crtc->dev;1140 struct radeon_device *rdev = dev->dev_private;1141 struct drm_framebuffer *target_fb;1142 struct drm_gem_object *obj;1143 struct radeon_bo *rbo;1144 uint64_t fb_location;1145 uint32_t fb_format, fb_pitch_pixels, tiling_flags;1146 unsigned bankw, bankh, mtaspect, tile_split;1147 u32 fb_swap = EVERGREEN_GRPH_ENDIAN_SWAP(EVERGREEN_GRPH_ENDIAN_NONE);1148 u32 tmp, viewport_w, viewport_h;1149 int r;1150 bool bypass_lut = false;1151 1152 /* no fb bound */1153 if (!atomic && !crtc->primary->fb) {1154 DRM_DEBUG_KMS("No FB bound\n");1155 return 0;1156 }1157 1158 if (atomic)1159 target_fb = fb;1160 else1161 target_fb = crtc->primary->fb;1162 1163 /* If atomic, assume fb object is pinned & idle & fenced and1164 * just update base pointers1165 */1166 obj = target_fb->obj[0];1167 rbo = gem_to_radeon_bo(obj);1168 r = radeon_bo_reserve(rbo, false);1169 if (unlikely(r != 0))1170 return r;1171 1172 if (atomic)1173 fb_location = radeon_bo_gpu_offset(rbo);1174 else {1175 r = radeon_bo_pin(rbo, RADEON_GEM_DOMAIN_VRAM, &fb_location);1176 if (unlikely(r != 0)) {1177 radeon_bo_unreserve(rbo);1178 return -EINVAL;1179 }1180 }1181 1182 radeon_bo_get_tiling_flags(rbo, &tiling_flags, NULL);1183 radeon_bo_unreserve(rbo);1184 1185 switch (target_fb->format->format) {1186 case DRM_FORMAT_C8:1187 fb_format = (EVERGREEN_GRPH_DEPTH(EVERGREEN_GRPH_DEPTH_8BPP) |1188 EVERGREEN_GRPH_FORMAT(EVERGREEN_GRPH_FORMAT_INDEXED));1189 break;1190 case DRM_FORMAT_XRGB4444:1191 case DRM_FORMAT_ARGB4444:1192 fb_format = (EVERGREEN_GRPH_DEPTH(EVERGREEN_GRPH_DEPTH_16BPP) |1193 EVERGREEN_GRPH_FORMAT(EVERGREEN_GRPH_FORMAT_ARGB4444));1194#ifdef __BIG_ENDIAN1195 fb_swap = EVERGREEN_GRPH_ENDIAN_SWAP(EVERGREEN_GRPH_ENDIAN_8IN16);1196#endif1197 break;1198 case DRM_FORMAT_XRGB1555:1199 case DRM_FORMAT_ARGB1555:1200 fb_format = (EVERGREEN_GRPH_DEPTH(EVERGREEN_GRPH_DEPTH_16BPP) |1201 EVERGREEN_GRPH_FORMAT(EVERGREEN_GRPH_FORMAT_ARGB1555));1202#ifdef __BIG_ENDIAN1203 fb_swap = EVERGREEN_GRPH_ENDIAN_SWAP(EVERGREEN_GRPH_ENDIAN_8IN16);1204#endif1205 break;1206 case DRM_FORMAT_BGRX5551:1207 case DRM_FORMAT_BGRA5551:1208 fb_format = (EVERGREEN_GRPH_DEPTH(EVERGREEN_GRPH_DEPTH_16BPP) |1209 EVERGREEN_GRPH_FORMAT(EVERGREEN_GRPH_FORMAT_BGRA5551));1210#ifdef __BIG_ENDIAN1211 fb_swap = EVERGREEN_GRPH_ENDIAN_SWAP(EVERGREEN_GRPH_ENDIAN_8IN16);1212#endif1213 break;1214 case DRM_FORMAT_RGB565:1215 fb_format = (EVERGREEN_GRPH_DEPTH(EVERGREEN_GRPH_DEPTH_16BPP) |1216 EVERGREEN_GRPH_FORMAT(EVERGREEN_GRPH_FORMAT_ARGB565));1217#ifdef __BIG_ENDIAN1218 fb_swap = EVERGREEN_GRPH_ENDIAN_SWAP(EVERGREEN_GRPH_ENDIAN_8IN16);1219#endif1220 break;1221 case DRM_FORMAT_XRGB8888:1222 case DRM_FORMAT_ARGB8888:1223 fb_format = (EVERGREEN_GRPH_DEPTH(EVERGREEN_GRPH_DEPTH_32BPP) |1224 EVERGREEN_GRPH_FORMAT(EVERGREEN_GRPH_FORMAT_ARGB8888));1225#ifdef __BIG_ENDIAN1226 fb_swap = EVERGREEN_GRPH_ENDIAN_SWAP(EVERGREEN_GRPH_ENDIAN_8IN32);1227#endif1228 break;1229 case DRM_FORMAT_XRGB2101010:1230 case DRM_FORMAT_ARGB2101010:1231 fb_format = (EVERGREEN_GRPH_DEPTH(EVERGREEN_GRPH_DEPTH_32BPP) |1232 EVERGREEN_GRPH_FORMAT(EVERGREEN_GRPH_FORMAT_ARGB2101010));1233#ifdef __BIG_ENDIAN1234 fb_swap = EVERGREEN_GRPH_ENDIAN_SWAP(EVERGREEN_GRPH_ENDIAN_8IN32);1235#endif1236 /* Greater 8 bpc fb needs to bypass hw-lut to retain precision */1237 bypass_lut = true;1238 break;1239 case DRM_FORMAT_BGRX1010102:1240 case DRM_FORMAT_BGRA1010102:1241 fb_format = (EVERGREEN_GRPH_DEPTH(EVERGREEN_GRPH_DEPTH_32BPP) |1242 EVERGREEN_GRPH_FORMAT(EVERGREEN_GRPH_FORMAT_BGRA1010102));1243#ifdef __BIG_ENDIAN1244 fb_swap = EVERGREEN_GRPH_ENDIAN_SWAP(EVERGREEN_GRPH_ENDIAN_8IN32);1245#endif1246 /* Greater 8 bpc fb needs to bypass hw-lut to retain precision */1247 bypass_lut = true;1248 break;1249 case DRM_FORMAT_XBGR8888:1250 case DRM_FORMAT_ABGR8888:1251 fb_format = (EVERGREEN_GRPH_DEPTH(EVERGREEN_GRPH_DEPTH_32BPP) |1252 EVERGREEN_GRPH_FORMAT(EVERGREEN_GRPH_FORMAT_ARGB8888));1253 fb_swap = (EVERGREEN_GRPH_RED_CROSSBAR(EVERGREEN_GRPH_RED_SEL_B) |1254 EVERGREEN_GRPH_BLUE_CROSSBAR(EVERGREEN_GRPH_BLUE_SEL_R));1255#ifdef __BIG_ENDIAN1256 fb_swap |= EVERGREEN_GRPH_ENDIAN_SWAP(EVERGREEN_GRPH_ENDIAN_8IN32);1257#endif1258 break;1259 default:1260 DRM_ERROR("Unsupported screen format %p4cc\n",1261 &target_fb->format->format);1262 return -EINVAL;1263 }1264 1265 if (tiling_flags & RADEON_TILING_MACRO) {1266 evergreen_tiling_fields(tiling_flags, &bankw, &bankh, &mtaspect, &tile_split);1267 1268 /* Set NUM_BANKS. */1269 if (rdev->family >= CHIP_TAHITI) {1270 unsigned index, num_banks;1271 1272 if (rdev->family >= CHIP_BONAIRE) {1273 unsigned tileb, tile_split_bytes;1274 1275 /* Calculate the macrotile mode index. */1276 tile_split_bytes = 64 << tile_split;1277 tileb = 8 * 8 * target_fb->format->cpp[0];1278 tileb = min(tile_split_bytes, tileb);1279 1280 for (index = 0; tileb > 64; index++)1281 tileb >>= 1;1282 1283 if (index >= 16) {1284 DRM_ERROR("Wrong screen bpp (%u) or tile split (%u)\n",1285 target_fb->format->cpp[0] * 8,1286 tile_split);1287 return -EINVAL;1288 }1289 1290 num_banks = (rdev->config.cik.macrotile_mode_array[index] >> 6) & 0x3;1291 } else {1292 switch (target_fb->format->cpp[0] * 8) {1293 case 8:1294 index = 10;1295 break;1296 case 16:1297 index = SI_TILE_MODE_COLOR_2D_SCANOUT_16BPP;1298 break;1299 default:1300 case 32:1301 index = SI_TILE_MODE_COLOR_2D_SCANOUT_32BPP;1302 break;1303 }1304 1305 num_banks = (rdev->config.si.tile_mode_array[index] >> 20) & 0x3;1306 }1307 1308 fb_format |= EVERGREEN_GRPH_NUM_BANKS(num_banks);1309 } else {1310 /* NI and older. */1311 if (rdev->family >= CHIP_CAYMAN)1312 tmp = rdev->config.cayman.tile_config;1313 else1314 tmp = rdev->config.evergreen.tile_config;1315 1316 switch ((tmp & 0xf0) >> 4) {1317 case 0: /* 4 banks */1318 fb_format |= EVERGREEN_GRPH_NUM_BANKS(EVERGREEN_ADDR_SURF_4_BANK);1319 break;1320 case 1: /* 8 banks */1321 default:1322 fb_format |= EVERGREEN_GRPH_NUM_BANKS(EVERGREEN_ADDR_SURF_8_BANK);1323 break;1324 case 2: /* 16 banks */1325 fb_format |= EVERGREEN_GRPH_NUM_BANKS(EVERGREEN_ADDR_SURF_16_BANK);1326 break;1327 }1328 }1329 1330 fb_format |= EVERGREEN_GRPH_ARRAY_MODE(EVERGREEN_GRPH_ARRAY_2D_TILED_THIN1);1331 fb_format |= EVERGREEN_GRPH_TILE_SPLIT(tile_split);1332 fb_format |= EVERGREEN_GRPH_BANK_WIDTH(bankw);1333 fb_format |= EVERGREEN_GRPH_BANK_HEIGHT(bankh);1334 fb_format |= EVERGREEN_GRPH_MACRO_TILE_ASPECT(mtaspect);1335 if (rdev->family >= CHIP_BONAIRE) {1336 /* XXX need to know more about the surface tiling mode */1337 fb_format |= CIK_GRPH_MICRO_TILE_MODE(CIK_DISPLAY_MICRO_TILING);1338 }1339 } else if (tiling_flags & RADEON_TILING_MICRO)1340 fb_format |= EVERGREEN_GRPH_ARRAY_MODE(EVERGREEN_GRPH_ARRAY_1D_TILED_THIN1);1341 1342 if (rdev->family >= CHIP_BONAIRE) {1343 /* Read the pipe config from the 2D TILED SCANOUT mode.1344 * It should be the same for the other modes too, but not all1345 * modes set the pipe config field. */1346 u32 pipe_config = (rdev->config.cik.tile_mode_array[10] >> 6) & 0x1f;1347 1348 fb_format |= CIK_GRPH_PIPE_CONFIG(pipe_config);1349 } else if ((rdev->family == CHIP_TAHITI) ||1350 (rdev->family == CHIP_PITCAIRN))1351 fb_format |= SI_GRPH_PIPE_CONFIG(SI_ADDR_SURF_P8_32x32_8x16);1352 else if ((rdev->family == CHIP_VERDE) ||1353 (rdev->family == CHIP_OLAND) ||1354 (rdev->family == CHIP_HAINAN)) /* for completeness. HAINAN has no display hw */1355 fb_format |= SI_GRPH_PIPE_CONFIG(SI_ADDR_SURF_P4_8x16);1356 1357 switch (radeon_crtc->crtc_id) {1358 case 0:1359 WREG32(AVIVO_D1VGA_CONTROL, 0);1360 break;1361 case 1:1362 WREG32(AVIVO_D2VGA_CONTROL, 0);1363 break;1364 case 2:1365 WREG32(EVERGREEN_D3VGA_CONTROL, 0);1366 break;1367 case 3:1368 WREG32(EVERGREEN_D4VGA_CONTROL, 0);1369 break;1370 case 4:1371 WREG32(EVERGREEN_D5VGA_CONTROL, 0);1372 break;1373 case 5:1374 WREG32(EVERGREEN_D6VGA_CONTROL, 0);1375 break;1376 default:1377 break;1378 }1379 1380 /* Make sure surface address is updated at vertical blank rather than1381 * horizontal blank1382 */1383 WREG32(EVERGREEN_GRPH_FLIP_CONTROL + radeon_crtc->crtc_offset, 0);1384 1385 WREG32(EVERGREEN_GRPH_PRIMARY_SURFACE_ADDRESS_HIGH + radeon_crtc->crtc_offset,1386 upper_32_bits(fb_location));1387 WREG32(EVERGREEN_GRPH_SECONDARY_SURFACE_ADDRESS_HIGH + radeon_crtc->crtc_offset,1388 upper_32_bits(fb_location));1389 WREG32(EVERGREEN_GRPH_PRIMARY_SURFACE_ADDRESS + radeon_crtc->crtc_offset,1390 (u32)fb_location & EVERGREEN_GRPH_SURFACE_ADDRESS_MASK);1391 WREG32(EVERGREEN_GRPH_SECONDARY_SURFACE_ADDRESS + radeon_crtc->crtc_offset,1392 (u32) fb_location & EVERGREEN_GRPH_SURFACE_ADDRESS_MASK);1393 WREG32(EVERGREEN_GRPH_CONTROL + radeon_crtc->crtc_offset, fb_format);1394 WREG32(EVERGREEN_GRPH_SWAP_CONTROL + radeon_crtc->crtc_offset, fb_swap);1395 1396 /*1397 * The LUT only has 256 slots for indexing by a 8 bpc fb. Bypass the LUT1398 * for > 8 bpc scanout to avoid truncation of fb indices to 8 msb's, to1399 * retain the full precision throughout the pipeline.1400 */1401 WREG32_P(EVERGREEN_GRPH_LUT_10BIT_BYPASS_CONTROL + radeon_crtc->crtc_offset,1402 (bypass_lut ? EVERGREEN_LUT_10BIT_BYPASS_EN : 0),1403 ~EVERGREEN_LUT_10BIT_BYPASS_EN);1404 1405 if (bypass_lut)1406 DRM_DEBUG_KMS("Bypassing hardware LUT due to 10 bit fb scanout.\n");1407 1408 WREG32(EVERGREEN_GRPH_SURFACE_OFFSET_X + radeon_crtc->crtc_offset, 0);1409 WREG32(EVERGREEN_GRPH_SURFACE_OFFSET_Y + radeon_crtc->crtc_offset, 0);1410 WREG32(EVERGREEN_GRPH_X_START + radeon_crtc->crtc_offset, 0);1411 WREG32(EVERGREEN_GRPH_Y_START + radeon_crtc->crtc_offset, 0);1412 WREG32(EVERGREEN_GRPH_X_END + radeon_crtc->crtc_offset, target_fb->width);1413 WREG32(EVERGREEN_GRPH_Y_END + radeon_crtc->crtc_offset, target_fb->height);1414 1415 fb_pitch_pixels = target_fb->pitches[0] / target_fb->format->cpp[0];1416 WREG32(EVERGREEN_GRPH_PITCH + radeon_crtc->crtc_offset, fb_pitch_pixels);1417 WREG32(EVERGREEN_GRPH_ENABLE + radeon_crtc->crtc_offset, 1);1418 1419 if (rdev->family >= CHIP_BONAIRE)1420 WREG32(CIK_LB_DESKTOP_HEIGHT + radeon_crtc->crtc_offset,1421 target_fb->height);1422 else1423 WREG32(EVERGREEN_DESKTOP_HEIGHT + radeon_crtc->crtc_offset,1424 target_fb->height);1425 x &= ~3;1426 y &= ~1;1427 WREG32(EVERGREEN_VIEWPORT_START + radeon_crtc->crtc_offset,1428 (x << 16) | y);1429 viewport_w = crtc->mode.hdisplay;1430 viewport_h = (crtc->mode.vdisplay + 1) & ~1;1431 if ((rdev->family >= CHIP_BONAIRE) &&1432 (crtc->mode.flags & DRM_MODE_FLAG_INTERLACE))1433 viewport_h *= 2;1434 WREG32(EVERGREEN_VIEWPORT_SIZE + radeon_crtc->crtc_offset,1435 (viewport_w << 16) | viewport_h);1436 1437 /* set pageflip to happen anywhere in vblank interval */1438 WREG32(EVERGREEN_MASTER_UPDATE_MODE + radeon_crtc->crtc_offset, 0);1439 1440 if (!atomic && fb && fb != crtc->primary->fb) {1441 rbo = gem_to_radeon_bo(fb->obj[0]);1442 r = radeon_bo_reserve(rbo, false);1443 if (unlikely(r != 0))1444 return r;1445 radeon_bo_unpin(rbo);1446 radeon_bo_unreserve(rbo);1447 }1448 1449 /* Bytes per pixel may have changed */1450 radeon_bandwidth_update(rdev);1451 1452 return 0;1453}1454 1455static int avivo_crtc_do_set_base(struct drm_crtc *crtc,1456 struct drm_framebuffer *fb,1457 int x, int y, int atomic)1458{1459 struct radeon_crtc *radeon_crtc = to_radeon_crtc(crtc);1460 struct drm_device *dev = crtc->dev;1461 struct radeon_device *rdev = dev->dev_private;1462 struct drm_gem_object *obj;1463 struct radeon_bo *rbo;1464 struct drm_framebuffer *target_fb;1465 uint64_t fb_location;1466 uint32_t fb_format, fb_pitch_pixels, tiling_flags;1467 u32 fb_swap = R600_D1GRPH_SWAP_ENDIAN_NONE;1468 u32 viewport_w, viewport_h;1469 int r;1470 bool bypass_lut = false;1471 1472 /* no fb bound */1473 if (!atomic && !crtc->primary->fb) {1474 DRM_DEBUG_KMS("No FB bound\n");1475 return 0;1476 }1477 1478 if (atomic)1479 target_fb = fb;1480 else1481 target_fb = crtc->primary->fb;1482 1483 obj = target_fb->obj[0];1484 rbo = gem_to_radeon_bo(obj);1485 r = radeon_bo_reserve(rbo, false);1486 if (unlikely(r != 0))1487 return r;1488 1489 /* If atomic, assume fb object is pinned & idle & fenced and1490 * just update base pointers1491 */1492 if (atomic)1493 fb_location = radeon_bo_gpu_offset(rbo);1494 else {1495 r = radeon_bo_pin(rbo, RADEON_GEM_DOMAIN_VRAM, &fb_location);1496 if (unlikely(r != 0)) {1497 radeon_bo_unreserve(rbo);1498 return -EINVAL;1499 }1500 }1501 radeon_bo_get_tiling_flags(rbo, &tiling_flags, NULL);1502 radeon_bo_unreserve(rbo);1503 1504 switch (target_fb->format->format) {1505 case DRM_FORMAT_C8:1506 fb_format =1507 AVIVO_D1GRPH_CONTROL_DEPTH_8BPP |1508 AVIVO_D1GRPH_CONTROL_8BPP_INDEXED;1509 break;1510 case DRM_FORMAT_XRGB4444:1511 case DRM_FORMAT_ARGB4444:1512 fb_format =1513 AVIVO_D1GRPH_CONTROL_DEPTH_16BPP |1514 AVIVO_D1GRPH_CONTROL_16BPP_ARGB4444;1515#ifdef __BIG_ENDIAN1516 fb_swap = R600_D1GRPH_SWAP_ENDIAN_16BIT;1517#endif1518 break;1519 case DRM_FORMAT_XRGB1555:1520 fb_format =1521 AVIVO_D1GRPH_CONTROL_DEPTH_16BPP |1522 AVIVO_D1GRPH_CONTROL_16BPP_ARGB1555;1523#ifdef __BIG_ENDIAN1524 fb_swap = R600_D1GRPH_SWAP_ENDIAN_16BIT;1525#endif1526 break;1527 case DRM_FORMAT_RGB565:1528 fb_format =1529 AVIVO_D1GRPH_CONTROL_DEPTH_16BPP |1530 AVIVO_D1GRPH_CONTROL_16BPP_RGB565;1531#ifdef __BIG_ENDIAN1532 fb_swap = R600_D1GRPH_SWAP_ENDIAN_16BIT;1533#endif1534 break;1535 case DRM_FORMAT_XRGB8888:1536 case DRM_FORMAT_ARGB8888:1537 fb_format =1538 AVIVO_D1GRPH_CONTROL_DEPTH_32BPP |1539 AVIVO_D1GRPH_CONTROL_32BPP_ARGB8888;1540#ifdef __BIG_ENDIAN1541 fb_swap = R600_D1GRPH_SWAP_ENDIAN_32BIT;1542#endif1543 break;1544 case DRM_FORMAT_XRGB2101010:1545 case DRM_FORMAT_ARGB2101010:1546 fb_format =1547 AVIVO_D1GRPH_CONTROL_DEPTH_32BPP |1548 AVIVO_D1GRPH_CONTROL_32BPP_ARGB2101010;1549#ifdef __BIG_ENDIAN1550 fb_swap = R600_D1GRPH_SWAP_ENDIAN_32BIT;1551#endif1552 /* Greater 8 bpc fb needs to bypass hw-lut to retain precision */1553 bypass_lut = true;1554 break;1555 case DRM_FORMAT_XBGR8888:1556 case DRM_FORMAT_ABGR8888:1557 fb_format =1558 AVIVO_D1GRPH_CONTROL_DEPTH_32BPP |1559 AVIVO_D1GRPH_CONTROL_32BPP_ARGB8888;1560 if (rdev->family >= CHIP_R600)1561 fb_swap =1562 (R600_D1GRPH_RED_CROSSBAR(R600_D1GRPH_RED_SEL_B) |1563 R600_D1GRPH_BLUE_CROSSBAR(R600_D1GRPH_BLUE_SEL_R));1564 else /* DCE1 (R5xx) */1565 fb_format |= AVIVO_D1GRPH_SWAP_RB;1566#ifdef __BIG_ENDIAN1567 fb_swap |= R600_D1GRPH_SWAP_ENDIAN_32BIT;1568#endif1569 break;1570 default:1571 DRM_ERROR("Unsupported screen format %p4cc\n",1572 &target_fb->format->format);1573 return -EINVAL;1574 }1575 1576 if (rdev->family >= CHIP_R600) {1577 if (tiling_flags & RADEON_TILING_MACRO)1578 fb_format |= R600_D1GRPH_ARRAY_MODE_2D_TILED_THIN1;1579 else if (tiling_flags & RADEON_TILING_MICRO)1580 fb_format |= R600_D1GRPH_ARRAY_MODE_1D_TILED_THIN1;1581 } else {1582 if (tiling_flags & RADEON_TILING_MACRO)1583 fb_format |= AVIVO_D1GRPH_MACRO_ADDRESS_MODE;1584 1585 if (tiling_flags & RADEON_TILING_MICRO)1586 fb_format |= AVIVO_D1GRPH_TILED;1587 }1588 1589 if (radeon_crtc->crtc_id == 0)1590 WREG32(AVIVO_D1VGA_CONTROL, 0);1591 else1592 WREG32(AVIVO_D2VGA_CONTROL, 0);1593 1594 /* Make sure surface address is update at vertical blank rather than1595 * horizontal blank1596 */1597 WREG32(AVIVO_D1GRPH_FLIP_CONTROL + radeon_crtc->crtc_offset, 0);1598 1599 if (rdev->family >= CHIP_RV770) {1600 if (radeon_crtc->crtc_id) {1601 WREG32(R700_D2GRPH_PRIMARY_SURFACE_ADDRESS_HIGH, upper_32_bits(fb_location));1602 WREG32(R700_D2GRPH_SECONDARY_SURFACE_ADDRESS_HIGH, upper_32_bits(fb_location));1603 } else {1604 WREG32(R700_D1GRPH_PRIMARY_SURFACE_ADDRESS_HIGH, upper_32_bits(fb_location));1605 WREG32(R700_D1GRPH_SECONDARY_SURFACE_ADDRESS_HIGH, upper_32_bits(fb_location));1606 }1607 }1608 WREG32(AVIVO_D1GRPH_PRIMARY_SURFACE_ADDRESS + radeon_crtc->crtc_offset,1609 (u32) fb_location);1610 WREG32(AVIVO_D1GRPH_SECONDARY_SURFACE_ADDRESS +1611 radeon_crtc->crtc_offset, (u32) fb_location);1612 WREG32(AVIVO_D1GRPH_CONTROL + radeon_crtc->crtc_offset, fb_format);1613 if (rdev->family >= CHIP_R600)1614 WREG32(R600_D1GRPH_SWAP_CONTROL + radeon_crtc->crtc_offset, fb_swap);1615 1616 /* LUT only has 256 slots for 8 bpc fb. Bypass for > 8 bpc scanout for precision */1617 WREG32_P(AVIVO_D1GRPH_LUT_SEL + radeon_crtc->crtc_offset,1618 (bypass_lut ? AVIVO_LUT_10BIT_BYPASS_EN : 0), ~AVIVO_LUT_10BIT_BYPASS_EN);1619 1620 if (bypass_lut)1621 DRM_DEBUG_KMS("Bypassing hardware LUT due to 10 bit fb scanout.\n");1622 1623 WREG32(AVIVO_D1GRPH_SURFACE_OFFSET_X + radeon_crtc->crtc_offset, 0);1624 WREG32(AVIVO_D1GRPH_SURFACE_OFFSET_Y + radeon_crtc->crtc_offset, 0);1625 WREG32(AVIVO_D1GRPH_X_START + radeon_crtc->crtc_offset, 0);1626 WREG32(AVIVO_D1GRPH_Y_START + radeon_crtc->crtc_offset, 0);1627 WREG32(AVIVO_D1GRPH_X_END + radeon_crtc->crtc_offset, target_fb->width);1628 WREG32(AVIVO_D1GRPH_Y_END + radeon_crtc->crtc_offset, target_fb->height);1629 1630 fb_pitch_pixels = target_fb->pitches[0] / target_fb->format->cpp[0];1631 WREG32(AVIVO_D1GRPH_PITCH + radeon_crtc->crtc_offset, fb_pitch_pixels);1632 WREG32(AVIVO_D1GRPH_ENABLE + radeon_crtc->crtc_offset, 1);1633 1634 WREG32(AVIVO_D1MODE_DESKTOP_HEIGHT + radeon_crtc->crtc_offset,1635 target_fb->height);1636 x &= ~3;1637 y &= ~1;1638 WREG32(AVIVO_D1MODE_VIEWPORT_START + radeon_crtc->crtc_offset,1639 (x << 16) | y);1640 viewport_w = crtc->mode.hdisplay;1641 viewport_h = (crtc->mode.vdisplay + 1) & ~1;1642 WREG32(AVIVO_D1MODE_VIEWPORT_SIZE + radeon_crtc->crtc_offset,1643 (viewport_w << 16) | viewport_h);1644 1645 /* set pageflip to happen only at start of vblank interval (front porch) */1646 WREG32(AVIVO_D1MODE_MASTER_UPDATE_MODE + radeon_crtc->crtc_offset, 3);1647 1648 if (!atomic && fb && fb != crtc->primary->fb) {1649 rbo = gem_to_radeon_bo(fb->obj[0]);1650 r = radeon_bo_reserve(rbo, false);1651 if (unlikely(r != 0))1652 return r;1653 radeon_bo_unpin(rbo);1654 radeon_bo_unreserve(rbo);1655 }1656 1657 /* Bytes per pixel may have changed */1658 radeon_bandwidth_update(rdev);1659 1660 return 0;1661}1662 1663int atombios_crtc_set_base(struct drm_crtc *crtc, int x, int y,1664 struct drm_framebuffer *old_fb)1665{1666 struct drm_device *dev = crtc->dev;1667 struct radeon_device *rdev = dev->dev_private;1668 1669 if (ASIC_IS_DCE4(rdev))1670 return dce4_crtc_do_set_base(crtc, old_fb, x, y, 0);1671 else if (ASIC_IS_AVIVO(rdev))1672 return avivo_crtc_do_set_base(crtc, old_fb, x, y, 0);1673 else1674 return radeon_crtc_do_set_base(crtc, old_fb, x, y, 0);1675}1676 1677int atombios_crtc_set_base_atomic(struct drm_crtc *crtc,1678 struct drm_framebuffer *fb,1679 int x, int y, enum mode_set_atomic state)1680{1681 struct drm_device *dev = crtc->dev;1682 struct radeon_device *rdev = dev->dev_private;1683 1684 if (ASIC_IS_DCE4(rdev))1685 return dce4_crtc_do_set_base(crtc, fb, x, y, 1);1686 else if (ASIC_IS_AVIVO(rdev))1687 return avivo_crtc_do_set_base(crtc, fb, x, y, 1);1688 else1689 return radeon_crtc_do_set_base(crtc, fb, x, y, 1);1690}1691 1692/* properly set additional regs when using atombios */1693static void radeon_legacy_atom_fixup(struct drm_crtc *crtc)1694{1695 struct drm_device *dev = crtc->dev;1696 struct radeon_device *rdev = dev->dev_private;1697 struct radeon_crtc *radeon_crtc = to_radeon_crtc(crtc);1698 u32 disp_merge_cntl;1699 1700 switch (radeon_crtc->crtc_id) {1701 case 0:1702 disp_merge_cntl = RREG32(RADEON_DISP_MERGE_CNTL);1703 disp_merge_cntl &= ~RADEON_DISP_RGB_OFFSET_EN;1704 WREG32(RADEON_DISP_MERGE_CNTL, disp_merge_cntl);1705 break;1706 case 1:1707 disp_merge_cntl = RREG32(RADEON_DISP2_MERGE_CNTL);1708 disp_merge_cntl &= ~RADEON_DISP2_RGB_OFFSET_EN;1709 WREG32(RADEON_DISP2_MERGE_CNTL, disp_merge_cntl);1710 WREG32(RADEON_FP_H2_SYNC_STRT_WID, RREG32(RADEON_CRTC2_H_SYNC_STRT_WID));1711 WREG32(RADEON_FP_V2_SYNC_STRT_WID, RREG32(RADEON_CRTC2_V_SYNC_STRT_WID));1712 break;1713 }1714}1715 1716/**1717 * radeon_get_pll_use_mask - look up a mask of which pplls are in use1718 *1719 * @crtc: drm crtc1720 *1721 * Returns the mask of which PPLLs (Pixel PLLs) are in use.1722 */1723static u32 radeon_get_pll_use_mask(struct drm_crtc *crtc)1724{1725 struct drm_device *dev = crtc->dev;1726 struct drm_crtc *test_crtc;1727 struct radeon_crtc *test_radeon_crtc;1728 u32 pll_in_use = 0;1729 1730 list_for_each_entry(test_crtc, &dev->mode_config.crtc_list, head) {1731 if (crtc == test_crtc)1732 continue;1733 1734 test_radeon_crtc = to_radeon_crtc(test_crtc);1735 if (test_radeon_crtc->pll_id != ATOM_PPLL_INVALID)1736 pll_in_use |= (1 << test_radeon_crtc->pll_id);1737 }1738 return pll_in_use;1739}1740 1741/**1742 * radeon_get_shared_dp_ppll - return the PPLL used by another crtc for DP1743 *1744 * @crtc: drm crtc1745 *1746 * Returns the PPLL (Pixel PLL) used by another crtc/encoder which is1747 * also in DP mode. For DP, a single PPLL can be used for all DP1748 * crtcs/encoders.1749 */1750static int radeon_get_shared_dp_ppll(struct drm_crtc *crtc)1751{1752 struct drm_device *dev = crtc->dev;1753 struct radeon_device *rdev = dev->dev_private;1754 struct drm_crtc *test_crtc;1755 struct radeon_crtc *test_radeon_crtc;1756 1757 list_for_each_entry(test_crtc, &dev->mode_config.crtc_list, head) {1758 if (crtc == test_crtc)1759 continue;1760 test_radeon_crtc = to_radeon_crtc(test_crtc);1761 if (test_radeon_crtc->encoder &&1762 ENCODER_MODE_IS_DP(atombios_get_encoder_mode(test_radeon_crtc->encoder))) {1763 /* PPLL2 is exclusive to UNIPHYA on DCE61 */1764 if (ASIC_IS_DCE61(rdev) && !ASIC_IS_DCE8(rdev) &&1765 test_radeon_crtc->pll_id == ATOM_PPLL2)1766 continue;1767 /* for DP use the same PLL for all */1768 if (test_radeon_crtc->pll_id != ATOM_PPLL_INVALID)1769 return test_radeon_crtc->pll_id;1770 }1771 }1772 return ATOM_PPLL_INVALID;1773}1774 1775/**1776 * radeon_get_shared_nondp_ppll - return the PPLL used by another non-DP crtc1777 *1778 * @crtc: drm crtc1779 *1780 * Returns the PPLL (Pixel PLL) used by another non-DP crtc/encoder which can1781 * be shared (i.e., same clock).1782 */1783static int radeon_get_shared_nondp_ppll(struct drm_crtc *crtc)1784{1785 struct radeon_crtc *radeon_crtc = to_radeon_crtc(crtc);1786 struct drm_device *dev = crtc->dev;1787 struct radeon_device *rdev = dev->dev_private;1788 struct drm_crtc *test_crtc;1789 struct radeon_crtc *test_radeon_crtc;1790 u32 adjusted_clock, test_adjusted_clock;1791 1792 adjusted_clock = radeon_crtc->adjusted_clock;1793 1794 if (adjusted_clock == 0)1795 return ATOM_PPLL_INVALID;1796 1797 list_for_each_entry(test_crtc, &dev->mode_config.crtc_list, head) {1798 if (crtc == test_crtc)1799 continue;1800 test_radeon_crtc = to_radeon_crtc(test_crtc);1801 if (test_radeon_crtc->encoder &&1802 !ENCODER_MODE_IS_DP(atombios_get_encoder_mode(test_radeon_crtc->encoder))) {1803 /* PPLL2 is exclusive to UNIPHYA on DCE61 */1804 if (ASIC_IS_DCE61(rdev) && !ASIC_IS_DCE8(rdev) &&1805 test_radeon_crtc->pll_id == ATOM_PPLL2)1806 continue;1807 /* check if we are already driving this connector with another crtc */1808 if (test_radeon_crtc->connector == radeon_crtc->connector) {1809 /* if we are, return that pll */1810 if (test_radeon_crtc->pll_id != ATOM_PPLL_INVALID)1811 return test_radeon_crtc->pll_id;1812 }1813 /* for non-DP check the clock */1814 test_adjusted_clock = test_radeon_crtc->adjusted_clock;1815 if ((crtc->mode.clock == test_crtc->mode.clock) &&1816 (adjusted_clock == test_adjusted_clock) &&1817 (radeon_crtc->ss_enabled == test_radeon_crtc->ss_enabled) &&1818 (test_radeon_crtc->pll_id != ATOM_PPLL_INVALID))1819 return test_radeon_crtc->pll_id;1820 }1821 }1822 return ATOM_PPLL_INVALID;1823}1824 1825/**1826 * radeon_atom_pick_pll - Allocate a PPLL for use by the crtc.1827 *1828 * @crtc: drm crtc1829 *1830 * Returns the PPLL (Pixel PLL) to be used by the crtc. For DP monitors1831 * a single PPLL can be used for all DP crtcs/encoders. For non-DP1832 * monitors a dedicated PPLL must be used. If a particular board has1833 * an external DP PLL, return ATOM_PPLL_INVALID to skip PLL programming1834 * as there is no need to program the PLL itself. If we are not able to1835 * allocate a PLL, return ATOM_PPLL_INVALID to skip PLL programming to1836 * avoid messing up an existing monitor.1837 *1838 * Asic specific PLL information1839 *1840 * DCE 8.x1841 * KB/KV1842 * - PPLL1, PPLL2 are available for all UNIPHY (both DP and non-DP)1843 * CI1844 * - PPLL0, PPLL1, PPLL2 are available for all UNIPHY (both DP and non-DP) and DAC1845 *1846 * DCE 6.11847 * - PPLL2 is only available to UNIPHYA (both DP and non-DP)1848 * - PPLL0, PPLL1 are available for UNIPHYB/C/D/E/F (both DP and non-DP)1849 *1850 * DCE 6.01851 * - PPLL0 is available to all UNIPHY (DP only)1852 * - PPLL1, PPLL2 are available for all UNIPHY (both DP and non-DP) and DAC1853 *1854 * DCE 5.01855 * - DCPLL is available to all UNIPHY (DP only)1856 * - PPLL1, PPLL2 are available for all UNIPHY (both DP and non-DP) and DAC1857 *1858 * DCE 3.0/4.0/4.11859 * - PPLL1, PPLL2 are available for all UNIPHY (both DP and non-DP) and DAC1860 *1861 */1862static int radeon_atom_pick_pll(struct drm_crtc *crtc)1863{1864 struct radeon_crtc *radeon_crtc = to_radeon_crtc(crtc);1865 struct drm_device *dev = crtc->dev;1866 struct radeon_device *rdev = dev->dev_private;1867 struct radeon_encoder *radeon_encoder =1868 to_radeon_encoder(radeon_crtc->encoder);1869 u32 pll_in_use;1870 int pll;1871 1872 if (ASIC_IS_DCE8(rdev)) {1873 if (ENCODER_MODE_IS_DP(atombios_get_encoder_mode(radeon_crtc->encoder))) {1874 if (rdev->clock.dp_extclk)1875 /* skip PPLL programming if using ext clock */1876 return ATOM_PPLL_INVALID;1877 else {1878 /* use the same PPLL for all DP monitors */1879 pll = radeon_get_shared_dp_ppll(crtc);1880 if (pll != ATOM_PPLL_INVALID)1881 return pll;1882 }1883 } else {1884 /* use the same PPLL for all monitors with the same clock */1885 pll = radeon_get_shared_nondp_ppll(crtc);1886 if (pll != ATOM_PPLL_INVALID)1887 return pll;1888 }1889 /* otherwise, pick one of the plls */1890 if ((rdev->family == CHIP_KABINI) ||1891 (rdev->family == CHIP_MULLINS)) {1892 /* KB/ML has PPLL1 and PPLL2 */1893 pll_in_use = radeon_get_pll_use_mask(crtc);1894 if (!(pll_in_use & (1 << ATOM_PPLL2)))1895 return ATOM_PPLL2;1896 if (!(pll_in_use & (1 << ATOM_PPLL1)))1897 return ATOM_PPLL1;1898 DRM_ERROR("unable to allocate a PPLL\n");1899 return ATOM_PPLL_INVALID;1900 } else {1901 /* CI/KV has PPLL0, PPLL1, and PPLL2 */1902 pll_in_use = radeon_get_pll_use_mask(crtc);1903 if (!(pll_in_use & (1 << ATOM_PPLL2)))1904 return ATOM_PPLL2;1905 if (!(pll_in_use & (1 << ATOM_PPLL1)))1906 return ATOM_PPLL1;1907 if (!(pll_in_use & (1 << ATOM_PPLL0)))1908 return ATOM_PPLL0;1909 DRM_ERROR("unable to allocate a PPLL\n");1910 return ATOM_PPLL_INVALID;1911 }1912 } else if (ASIC_IS_DCE61(rdev)) {1913 struct radeon_encoder_atom_dig *dig =1914 radeon_encoder->enc_priv;1915 1916 if ((radeon_encoder->encoder_id == ENCODER_OBJECT_ID_INTERNAL_UNIPHY) &&1917 (dig->linkb == false))1918 /* UNIPHY A uses PPLL2 */1919 return ATOM_PPLL2;1920 else if (ENCODER_MODE_IS_DP(atombios_get_encoder_mode(radeon_crtc->encoder))) {1921 /* UNIPHY B/C/D/E/F */1922 if (rdev->clock.dp_extclk)1923 /* skip PPLL programming if using ext clock */1924 return ATOM_PPLL_INVALID;1925 else {1926 /* use the same PPLL for all DP monitors */1927 pll = radeon_get_shared_dp_ppll(crtc);1928 if (pll != ATOM_PPLL_INVALID)1929 return pll;1930 }1931 } else {1932 /* use the same PPLL for all monitors with the same clock */1933 pll = radeon_get_shared_nondp_ppll(crtc);1934 if (pll != ATOM_PPLL_INVALID)1935 return pll;1936 }1937 /* UNIPHY B/C/D/E/F */1938 pll_in_use = radeon_get_pll_use_mask(crtc);1939 if (!(pll_in_use & (1 << ATOM_PPLL0)))1940 return ATOM_PPLL0;1941 if (!(pll_in_use & (1 << ATOM_PPLL1)))1942 return ATOM_PPLL1;1943 DRM_ERROR("unable to allocate a PPLL\n");1944 return ATOM_PPLL_INVALID;1945 } else if (ASIC_IS_DCE41(rdev)) {1946 /* Don't share PLLs on DCE4.1 chips */1947 if (ENCODER_MODE_IS_DP(atombios_get_encoder_mode(radeon_crtc->encoder))) {1948 if (rdev->clock.dp_extclk)1949 /* skip PPLL programming if using ext clock */1950 return ATOM_PPLL_INVALID;1951 }1952 pll_in_use = radeon_get_pll_use_mask(crtc);1953 if (!(pll_in_use & (1 << ATOM_PPLL1)))1954 return ATOM_PPLL1;1955 if (!(pll_in_use & (1 << ATOM_PPLL2)))1956 return ATOM_PPLL2;1957 DRM_ERROR("unable to allocate a PPLL\n");1958 return ATOM_PPLL_INVALID;1959 } else if (ASIC_IS_DCE4(rdev)) {1960 /* in DP mode, the DP ref clock can come from PPLL, DCPLL, or ext clock,1961 * depending on the asic:1962 * DCE4: PPLL or ext clock1963 * DCE5: PPLL, DCPLL, or ext clock1964 * DCE6: PPLL, PPLL0, or ext clock1965 *1966 * Setting ATOM_PPLL_INVALID will cause SetPixelClock to skip1967 * PPLL/DCPLL programming and only program the DP DTO for the1968 * crtc virtual pixel clock.1969 */1970 if (ENCODER_MODE_IS_DP(atombios_get_encoder_mode(radeon_crtc->encoder))) {1971 if (rdev->clock.dp_extclk)1972 /* skip PPLL programming if using ext clock */1973 return ATOM_PPLL_INVALID;1974 else if (ASIC_IS_DCE6(rdev))1975 /* use PPLL0 for all DP */1976 return ATOM_PPLL0;1977 else if (ASIC_IS_DCE5(rdev))1978 /* use DCPLL for all DP */1979 return ATOM_DCPLL;1980 else {1981 /* use the same PPLL for all DP monitors */1982 pll = radeon_get_shared_dp_ppll(crtc);1983 if (pll != ATOM_PPLL_INVALID)1984 return pll;1985 }1986 } else {1987 /* use the same PPLL for all monitors with the same clock */1988 pll = radeon_get_shared_nondp_ppll(crtc);1989 if (pll != ATOM_PPLL_INVALID)1990 return pll;1991 }1992 /* all other cases */1993 pll_in_use = radeon_get_pll_use_mask(crtc);1994 if (!(pll_in_use & (1 << ATOM_PPLL1)))1995 return ATOM_PPLL1;1996 if (!(pll_in_use & (1 << ATOM_PPLL2)))1997 return ATOM_PPLL2;1998 DRM_ERROR("unable to allocate a PPLL\n");1999 return ATOM_PPLL_INVALID;2000 } else {2001 /* on pre-R5xx asics, the crtc to pll mapping is hardcoded */2002 /* some atombios (observed in some DCE2/DCE3) code have a bug,2003 * the matching btw pll and crtc is done through2004 * PCLK_CRTC[1|2]_CNTL (0x480/0x484) but atombios code use the2005 * pll (1 or 2) to select which register to write. ie if using2006 * pll1 it will use PCLK_CRTC1_CNTL (0x480) and if using pll22007 * it will use PCLK_CRTC2_CNTL (0x484), it then use crtc id to2008 * choose which value to write. Which is reverse order from2009 * register logic. So only case that works is when pllid is2010 * same as crtcid or when both pll and crtc are enabled and2011 * both use same clock.2012 *2013 * So just return crtc id as if crtc and pll were hard linked2014 * together even if they aren't2015 */2016 return radeon_crtc->crtc_id;2017 }2018}2019 2020void radeon_atom_disp_eng_pll_init(struct radeon_device *rdev)2021{2022 /* always set DCPLL */2023 if (ASIC_IS_DCE6(rdev))2024 atombios_crtc_set_disp_eng_pll(rdev, rdev->clock.default_dispclk);2025 else if (ASIC_IS_DCE4(rdev)) {2026 struct radeon_atom_ss ss;2027 bool ss_enabled = radeon_atombios_get_asic_ss_info(rdev, &ss,2028 ASIC_INTERNAL_SS_ON_DCPLL,2029 rdev->clock.default_dispclk);2030 if (ss_enabled)2031 atombios_crtc_program_ss(rdev, ATOM_DISABLE, ATOM_DCPLL, -1, &ss);2032 /* XXX: DCE5, make sure voltage, dispclk is high enough */2033 atombios_crtc_set_disp_eng_pll(rdev, rdev->clock.default_dispclk);2034 if (ss_enabled)2035 atombios_crtc_program_ss(rdev, ATOM_ENABLE, ATOM_DCPLL, -1, &ss);2036 }2037 2038}2039 2040int atombios_crtc_mode_set(struct drm_crtc *crtc,2041 struct drm_display_mode *mode,2042 struct drm_display_mode *adjusted_mode,2043 int x, int y, struct drm_framebuffer *old_fb)2044{2045 struct radeon_crtc *radeon_crtc = to_radeon_crtc(crtc);2046 struct drm_device *dev = crtc->dev;2047 struct radeon_device *rdev = dev->dev_private;2048 struct radeon_encoder *radeon_encoder =2049 to_radeon_encoder(radeon_crtc->encoder);2050 bool is_tvcv = false;2051 2052 if (radeon_encoder->active_device &2053 (ATOM_DEVICE_TV_SUPPORT | ATOM_DEVICE_CV_SUPPORT))2054 is_tvcv = true;2055 2056 if (!radeon_crtc->adjusted_clock)2057 return -EINVAL;2058 2059 atombios_crtc_set_pll(crtc, adjusted_mode);2060 2061 if (ASIC_IS_DCE4(rdev))2062 atombios_set_crtc_dtd_timing(crtc, adjusted_mode);2063 else if (ASIC_IS_AVIVO(rdev)) {2064 if (is_tvcv)2065 atombios_crtc_set_timing(crtc, adjusted_mode);2066 else2067 atombios_set_crtc_dtd_timing(crtc, adjusted_mode);2068 } else {2069 atombios_crtc_set_timing(crtc, adjusted_mode);2070 if (radeon_crtc->crtc_id == 0)2071 atombios_set_crtc_dtd_timing(crtc, adjusted_mode);2072 radeon_legacy_atom_fixup(crtc);2073 }2074 atombios_crtc_set_base(crtc, x, y, old_fb);2075 atombios_overscan_setup(crtc, mode, adjusted_mode);2076 atombios_scaler_setup(crtc);2077 radeon_cursor_reset(crtc);2078 /* update the hw version fpr dpm */2079 radeon_crtc->hw_mode = *adjusted_mode;2080 2081 return 0;2082}2083 2084static bool atombios_crtc_mode_fixup(struct drm_crtc *crtc,2085 const struct drm_display_mode *mode,2086 struct drm_display_mode *adjusted_mode)2087{2088 struct radeon_crtc *radeon_crtc = to_radeon_crtc(crtc);2089 struct drm_device *dev = crtc->dev;2090 struct drm_encoder *encoder;2091 2092 /* assign the encoder to the radeon crtc to avoid repeated lookups later */2093 list_for_each_entry(encoder, &dev->mode_config.encoder_list, head) {2094 if (encoder->crtc == crtc) {2095 radeon_crtc->encoder = encoder;2096 radeon_crtc->connector = radeon_get_connector_for_encoder(encoder);2097 break;2098 }2099 }2100 if ((radeon_crtc->encoder == NULL) || (radeon_crtc->connector == NULL)) {2101 radeon_crtc->encoder = NULL;2102 radeon_crtc->connector = NULL;2103 return false;2104 }2105 if (radeon_crtc->encoder) {2106 struct radeon_encoder *radeon_encoder =2107 to_radeon_encoder(radeon_crtc->encoder);2108 2109 radeon_crtc->output_csc = radeon_encoder->output_csc;2110 }2111 if (!radeon_crtc_scaling_mode_fixup(crtc, mode, adjusted_mode))2112 return false;2113 if (!atombios_crtc_prepare_pll(crtc, adjusted_mode))2114 return false;2115 /* pick pll */2116 radeon_crtc->pll_id = radeon_atom_pick_pll(crtc);2117 /* if we can't get a PPLL for a non-DP encoder, fail */2118 if ((radeon_crtc->pll_id == ATOM_PPLL_INVALID) &&2119 !ENCODER_MODE_IS_DP(atombios_get_encoder_mode(radeon_crtc->encoder)))2120 return false;2121 2122 return true;2123}2124 2125static void atombios_crtc_prepare(struct drm_crtc *crtc)2126{2127 struct drm_device *dev = crtc->dev;2128 struct radeon_device *rdev = dev->dev_private;2129 2130 /* disable crtc pair power gating before programming */2131 if (ASIC_IS_DCE6(rdev))2132 atombios_powergate_crtc(crtc, ATOM_DISABLE);2133 2134 atombios_lock_crtc(crtc, ATOM_ENABLE);2135 atombios_crtc_dpms(crtc, DRM_MODE_DPMS_OFF);2136}2137 2138static void atombios_crtc_commit(struct drm_crtc *crtc)2139{2140 atombios_crtc_dpms(crtc, DRM_MODE_DPMS_ON);2141 atombios_lock_crtc(crtc, ATOM_DISABLE);2142}2143 2144static void atombios_crtc_disable(struct drm_crtc *crtc)2145{2146 struct radeon_crtc *radeon_crtc = to_radeon_crtc(crtc);2147 struct drm_device *dev = crtc->dev;2148 struct radeon_device *rdev = dev->dev_private;2149 struct radeon_atom_ss ss;2150 int i;2151 2152 atombios_crtc_dpms(crtc, DRM_MODE_DPMS_OFF);2153 if (crtc->primary->fb) {2154 int r;2155 struct radeon_bo *rbo;2156 2157 rbo = gem_to_radeon_bo(crtc->primary->fb->obj[0]);2158 r = radeon_bo_reserve(rbo, false);2159 if (unlikely(r))2160 DRM_ERROR("failed to reserve rbo before unpin\n");2161 else {2162 radeon_bo_unpin(rbo);2163 radeon_bo_unreserve(rbo);2164 }2165 }2166 /* disable the GRPH */2167 if (ASIC_IS_DCE4(rdev))2168 WREG32(EVERGREEN_GRPH_ENABLE + radeon_crtc->crtc_offset, 0);2169 else if (ASIC_IS_AVIVO(rdev))2170 WREG32(AVIVO_D1GRPH_ENABLE + radeon_crtc->crtc_offset, 0);2171 2172 if (ASIC_IS_DCE6(rdev))2173 atombios_powergate_crtc(crtc, ATOM_ENABLE);2174 2175 for (i = 0; i < rdev->num_crtc; i++) {2176 if (rdev->mode_info.crtcs[i] &&2177 rdev->mode_info.crtcs[i]->enabled &&2178 i != radeon_crtc->crtc_id &&2179 radeon_crtc->pll_id == rdev->mode_info.crtcs[i]->pll_id) {2180 /* one other crtc is using this pll don't turn2181 * off the pll2182 */2183 goto done;2184 }2185 }2186 2187 switch (radeon_crtc->pll_id) {2188 case ATOM_PPLL1:2189 case ATOM_PPLL2:2190 /* disable the ppll */2191 atombios_crtc_program_pll(crtc, radeon_crtc->crtc_id, radeon_crtc->pll_id,2192 0, 0, ATOM_DISABLE, 0, 0, 0, 0, 0, false, &ss);2193 break;2194 case ATOM_PPLL0:2195 /* disable the ppll */2196 if ((rdev->family == CHIP_ARUBA) ||2197 (rdev->family == CHIP_KAVERI) ||2198 (rdev->family == CHIP_BONAIRE) ||2199 (rdev->family == CHIP_HAWAII))2200 atombios_crtc_program_pll(crtc, radeon_crtc->crtc_id, radeon_crtc->pll_id,2201 0, 0, ATOM_DISABLE, 0, 0, 0, 0, 0, false, &ss);2202 break;2203 default:2204 break;2205 }2206done:2207 radeon_crtc->pll_id = ATOM_PPLL_INVALID;2208 radeon_crtc->adjusted_clock = 0;2209 radeon_crtc->encoder = NULL;2210 radeon_crtc->connector = NULL;2211}2212 2213static const struct drm_crtc_helper_funcs atombios_helper_funcs = {2214 .dpms = atombios_crtc_dpms,2215 .mode_fixup = atombios_crtc_mode_fixup,2216 .mode_set = atombios_crtc_mode_set,2217 .mode_set_base = atombios_crtc_set_base,2218 .mode_set_base_atomic = atombios_crtc_set_base_atomic,2219 .prepare = atombios_crtc_prepare,2220 .commit = atombios_crtc_commit,2221 .disable = atombios_crtc_disable,2222 .get_scanout_position = radeon_get_crtc_scanout_position,2223};2224 2225void radeon_atombios_init_crtc(struct drm_device *dev,2226 struct radeon_crtc *radeon_crtc)2227{2228 struct radeon_device *rdev = dev->dev_private;2229 2230 if (ASIC_IS_DCE4(rdev)) {2231 switch (radeon_crtc->crtc_id) {2232 case 0:2233 default:2234 radeon_crtc->crtc_offset = EVERGREEN_CRTC0_REGISTER_OFFSET;2235 break;2236 case 1:2237 radeon_crtc->crtc_offset = EVERGREEN_CRTC1_REGISTER_OFFSET;2238 break;2239 case 2:2240 radeon_crtc->crtc_offset = EVERGREEN_CRTC2_REGISTER_OFFSET;2241 break;2242 case 3:2243 radeon_crtc->crtc_offset = EVERGREEN_CRTC3_REGISTER_OFFSET;2244 break;2245 case 4:2246 radeon_crtc->crtc_offset = EVERGREEN_CRTC4_REGISTER_OFFSET;2247 break;2248 case 5:2249 radeon_crtc->crtc_offset = EVERGREEN_CRTC5_REGISTER_OFFSET;2250 break;2251 }2252 } else {2253 if (radeon_crtc->crtc_id == 1)2254 radeon_crtc->crtc_offset =2255 AVIVO_D2CRTC_H_TOTAL - AVIVO_D1CRTC_H_TOTAL;2256 else2257 radeon_crtc->crtc_offset = 0;2258 }2259 radeon_crtc->pll_id = ATOM_PPLL_INVALID;2260 radeon_crtc->adjusted_clock = 0;2261 radeon_crtc->encoder = NULL;2262 radeon_crtc->connector = NULL;2263 drm_crtc_helper_add(&radeon_crtc->base, &atombios_helper_funcs);2264}2265