root/drivers/gpu/drm/amd/amdgpu/atombios_crtc.c

/* [<][>][^][v][top][bottom][index][help] */

DEFINITIONS

This source file includes following definitions.
  1. amdgpu_atombios_crtc_overscan_setup
  2. amdgpu_atombios_crtc_scaler_setup
  3. amdgpu_atombios_crtc_lock
  4. amdgpu_atombios_crtc_enable
  5. amdgpu_atombios_crtc_blank
  6. amdgpu_atombios_crtc_powergate
  7. amdgpu_atombios_crtc_powergate_init
  8. amdgpu_atombios_crtc_set_dtd_timing
  9. amdgpu_atombios_crtc_program_ss
  10. amdgpu_atombios_crtc_adjust_pll
  11. amdgpu_atombios_crtc_set_disp_eng_pll
  12. amdgpu_atombios_crtc_set_dce_clock
  13. is_pixel_clock_source_from_pll
  14. amdgpu_atombios_crtc_program_pll
  15. amdgpu_atombios_crtc_prepare_pll
  16. amdgpu_atombios_crtc_set_pll

   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 a
   6  * copy of this software and associated documentation files (the "Software"),
   7  * to deal in the Software without restriction, including without limitation
   8  * the rights to use, copy, modify, merge, publish, distribute, sublicense,
   9  * and/or sell copies of the Software, and to permit persons to whom the
  10  * Software is furnished to do so, subject to the following conditions:
  11  *
  12  * The above copyright notice and this permission notice shall be included in
  13  * all copies or substantial portions of the Software.
  14  *
  15  * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
  16  * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
  17  * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.  IN NO EVENT SHALL
  18  * THE COPYRIGHT HOLDER(S) OR AUTHOR(S) BE LIABLE FOR ANY CLAIM, DAMAGES OR
  19  * 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 OR
  21  * OTHER DEALINGS IN THE SOFTWARE.
  22  *
  23  * Authors: Dave Airlie
  24  *          Alex Deucher
  25  */
  26 
  27 #include <drm/drm_crtc_helper.h>
  28 #include <drm/amdgpu_drm.h>
  29 #include <drm/drm_fixed.h>
  30 #include "amdgpu.h"
  31 #include "atom.h"
  32 #include "atom-bits.h"
  33 #include "atombios_encoders.h"
  34 #include "atombios_crtc.h"
  35 #include "amdgpu_atombios.h"
  36 #include "amdgpu_pll.h"
  37 #include "amdgpu_connectors.h"
  38 
  39 void amdgpu_atombios_crtc_overscan_setup(struct drm_crtc *crtc,
  40                                   struct drm_display_mode *mode,
  41                                   struct drm_display_mode *adjusted_mode)
  42 {
  43         struct drm_device *dev = crtc->dev;
  44         struct amdgpu_device *adev = dev->dev_private;
  45         struct amdgpu_crtc *amdgpu_crtc = to_amdgpu_crtc(crtc);
  46         SET_CRTC_OVERSCAN_PS_ALLOCATION args;
  47         int index = GetIndexIntoMasterTable(COMMAND, SetCRTC_OverScan);
  48         int a1, a2;
  49 
  50         memset(&args, 0, sizeof(args));
  51 
  52         args.ucCRTC = amdgpu_crtc->crtc_id;
  53 
  54         switch (amdgpu_crtc->rmx_type) {
  55         case RMX_CENTER:
  56                 args.usOverscanTop = cpu_to_le16((adjusted_mode->crtc_vdisplay - mode->crtc_vdisplay) / 2);
  57                 args.usOverscanBottom = cpu_to_le16((adjusted_mode->crtc_vdisplay - mode->crtc_vdisplay) / 2);
  58                 args.usOverscanLeft = cpu_to_le16((adjusted_mode->crtc_hdisplay - mode->crtc_hdisplay) / 2);
  59                 args.usOverscanRight = cpu_to_le16((adjusted_mode->crtc_hdisplay - mode->crtc_hdisplay) / 2);
  60                 break;
  61         case RMX_ASPECT:
  62                 a1 = mode->crtc_vdisplay * adjusted_mode->crtc_hdisplay;
  63                 a2 = adjusted_mode->crtc_vdisplay * mode->crtc_hdisplay;
  64 
  65                 if (a1 > a2) {
  66                         args.usOverscanLeft = cpu_to_le16((adjusted_mode->crtc_hdisplay - (a2 / mode->crtc_vdisplay)) / 2);
  67                         args.usOverscanRight = cpu_to_le16((adjusted_mode->crtc_hdisplay - (a2 / mode->crtc_vdisplay)) / 2);
  68                 } else if (a2 > a1) {
  69                         args.usOverscanTop = cpu_to_le16((adjusted_mode->crtc_vdisplay - (a1 / mode->crtc_hdisplay)) / 2);
  70                         args.usOverscanBottom = cpu_to_le16((adjusted_mode->crtc_vdisplay - (a1 / mode->crtc_hdisplay)) / 2);
  71                 }
  72                 break;
  73         case RMX_FULL:
  74         default:
  75                 args.usOverscanRight = cpu_to_le16(amdgpu_crtc->h_border);
  76                 args.usOverscanLeft = cpu_to_le16(amdgpu_crtc->h_border);
  77                 args.usOverscanBottom = cpu_to_le16(amdgpu_crtc->v_border);
  78                 args.usOverscanTop = cpu_to_le16(amdgpu_crtc->v_border);
  79                 break;
  80         }
  81         amdgpu_atom_execute_table(adev->mode_info.atom_context, index, (uint32_t *)&args);
  82 }
  83 
  84 void amdgpu_atombios_crtc_scaler_setup(struct drm_crtc *crtc)
  85 {
  86         struct drm_device *dev = crtc->dev;
  87         struct amdgpu_device *adev = dev->dev_private;
  88         struct amdgpu_crtc *amdgpu_crtc = to_amdgpu_crtc(crtc);
  89         ENABLE_SCALER_PS_ALLOCATION args;
  90         int index = GetIndexIntoMasterTable(COMMAND, EnableScaler);
  91 
  92         memset(&args, 0, sizeof(args));
  93 
  94         args.ucScaler = amdgpu_crtc->crtc_id;
  95 
  96         switch (amdgpu_crtc->rmx_type) {
  97         case RMX_FULL:
  98                 args.ucEnable = ATOM_SCALER_EXPANSION;
  99                 break;
 100         case RMX_CENTER:
 101                 args.ucEnable = ATOM_SCALER_CENTER;
 102                 break;
 103         case RMX_ASPECT:
 104                 args.ucEnable = ATOM_SCALER_EXPANSION;
 105                 break;
 106         default:
 107                 args.ucEnable = ATOM_SCALER_DISABLE;
 108                 break;
 109         }
 110         amdgpu_atom_execute_table(adev->mode_info.atom_context, index, (uint32_t *)&args);
 111 }
 112 
 113 void amdgpu_atombios_crtc_lock(struct drm_crtc *crtc, int lock)
 114 {
 115         struct amdgpu_crtc *amdgpu_crtc = to_amdgpu_crtc(crtc);
 116         struct drm_device *dev = crtc->dev;
 117         struct amdgpu_device *adev = dev->dev_private;
 118         int index =
 119             GetIndexIntoMasterTable(COMMAND, UpdateCRTC_DoubleBufferRegisters);
 120         ENABLE_CRTC_PS_ALLOCATION args;
 121 
 122         memset(&args, 0, sizeof(args));
 123 
 124         args.ucCRTC = amdgpu_crtc->crtc_id;
 125         args.ucEnable = lock;
 126 
 127         amdgpu_atom_execute_table(adev->mode_info.atom_context, index, (uint32_t *)&args);
 128 }
 129 
 130 void amdgpu_atombios_crtc_enable(struct drm_crtc *crtc, int state)
 131 {
 132         struct amdgpu_crtc *amdgpu_crtc = to_amdgpu_crtc(crtc);
 133         struct drm_device *dev = crtc->dev;
 134         struct amdgpu_device *adev = dev->dev_private;
 135         int index = GetIndexIntoMasterTable(COMMAND, EnableCRTC);
 136         ENABLE_CRTC_PS_ALLOCATION args;
 137 
 138         memset(&args, 0, sizeof(args));
 139 
 140         args.ucCRTC = amdgpu_crtc->crtc_id;
 141         args.ucEnable = state;
 142 
 143         amdgpu_atom_execute_table(adev->mode_info.atom_context, index, (uint32_t *)&args);
 144 }
 145 
 146 void amdgpu_atombios_crtc_blank(struct drm_crtc *crtc, int state)
 147 {
 148         struct amdgpu_crtc *amdgpu_crtc = to_amdgpu_crtc(crtc);
 149         struct drm_device *dev = crtc->dev;
 150         struct amdgpu_device *adev = dev->dev_private;
 151         int index = GetIndexIntoMasterTable(COMMAND, BlankCRTC);
 152         BLANK_CRTC_PS_ALLOCATION args;
 153 
 154         memset(&args, 0, sizeof(args));
 155 
 156         args.ucCRTC = amdgpu_crtc->crtc_id;
 157         args.ucBlanking = state;
 158 
 159         amdgpu_atom_execute_table(adev->mode_info.atom_context, index, (uint32_t *)&args);
 160 }
 161 
 162 void amdgpu_atombios_crtc_powergate(struct drm_crtc *crtc, int state)
 163 {
 164         struct amdgpu_crtc *amdgpu_crtc = to_amdgpu_crtc(crtc);
 165         struct drm_device *dev = crtc->dev;
 166         struct amdgpu_device *adev = dev->dev_private;
 167         int index = GetIndexIntoMasterTable(COMMAND, EnableDispPowerGating);
 168         ENABLE_DISP_POWER_GATING_PS_ALLOCATION args;
 169 
 170         memset(&args, 0, sizeof(args));
 171 
 172         args.ucDispPipeId = amdgpu_crtc->crtc_id;
 173         args.ucEnable = state;
 174 
 175         amdgpu_atom_execute_table(adev->mode_info.atom_context, index, (uint32_t *)&args);
 176 }
 177 
 178 void amdgpu_atombios_crtc_powergate_init(struct amdgpu_device *adev)
 179 {
 180         int index = GetIndexIntoMasterTable(COMMAND, EnableDispPowerGating);
 181         ENABLE_DISP_POWER_GATING_PS_ALLOCATION args;
 182 
 183         memset(&args, 0, sizeof(args));
 184 
 185         args.ucEnable = ATOM_INIT;
 186 
 187         amdgpu_atom_execute_table(adev->mode_info.atom_context, index, (uint32_t *)&args);
 188 }
 189 
 190 void amdgpu_atombios_crtc_set_dtd_timing(struct drm_crtc *crtc,
 191                                   struct drm_display_mode *mode)
 192 {
 193         struct amdgpu_crtc *amdgpu_crtc = to_amdgpu_crtc(crtc);
 194         struct drm_device *dev = crtc->dev;
 195         struct amdgpu_device *adev = dev->dev_private;
 196         SET_CRTC_USING_DTD_TIMING_PARAMETERS args;
 197         int index = GetIndexIntoMasterTable(COMMAND, SetCRTC_UsingDTDTiming);
 198         u16 misc = 0;
 199 
 200         memset(&args, 0, sizeof(args));
 201         args.usH_Size = cpu_to_le16(mode->crtc_hdisplay - (amdgpu_crtc->h_border * 2));
 202         args.usH_Blanking_Time =
 203                 cpu_to_le16(mode->crtc_hblank_end - mode->crtc_hdisplay + (amdgpu_crtc->h_border * 2));
 204         args.usV_Size = cpu_to_le16(mode->crtc_vdisplay - (amdgpu_crtc->v_border * 2));
 205         args.usV_Blanking_Time =
 206                 cpu_to_le16(mode->crtc_vblank_end - mode->crtc_vdisplay + (amdgpu_crtc->v_border * 2));
 207         args.usH_SyncOffset =
 208                 cpu_to_le16(mode->crtc_hsync_start - mode->crtc_hdisplay + amdgpu_crtc->h_border);
 209         args.usH_SyncWidth =
 210                 cpu_to_le16(mode->crtc_hsync_end - mode->crtc_hsync_start);
 211         args.usV_SyncOffset =
 212                 cpu_to_le16(mode->crtc_vsync_start - mode->crtc_vdisplay + amdgpu_crtc->v_border);
 213         args.usV_SyncWidth =
 214                 cpu_to_le16(mode->crtc_vsync_end - mode->crtc_vsync_start);
 215         args.ucH_Border = amdgpu_crtc->h_border;
 216         args.ucV_Border = amdgpu_crtc->v_border;
 217 
 218         if (mode->flags & DRM_MODE_FLAG_NVSYNC)
 219                 misc |= ATOM_VSYNC_POLARITY;
 220         if (mode->flags & DRM_MODE_FLAG_NHSYNC)
 221                 misc |= ATOM_HSYNC_POLARITY;
 222         if (mode->flags & DRM_MODE_FLAG_CSYNC)
 223                 misc |= ATOM_COMPOSITESYNC;
 224         if (mode->flags & DRM_MODE_FLAG_INTERLACE)
 225                 misc |= ATOM_INTERLACE;
 226         if (mode->flags & DRM_MODE_FLAG_DBLSCAN)
 227                 misc |= ATOM_DOUBLE_CLOCK_MODE;
 228 
 229         args.susModeMiscInfo.usAccess = cpu_to_le16(misc);
 230         args.ucCRTC = amdgpu_crtc->crtc_id;
 231 
 232         amdgpu_atom_execute_table(adev->mode_info.atom_context, index, (uint32_t *)&args);
 233 }
 234 
 235 union atom_enable_ss {
 236         ENABLE_SPREAD_SPECTRUM_ON_PPLL_PS_ALLOCATION v1;
 237         ENABLE_SPREAD_SPECTRUM_ON_PPLL_V2 v2;
 238         ENABLE_SPREAD_SPECTRUM_ON_PPLL_V3 v3;
 239 };
 240 
 241 static void amdgpu_atombios_crtc_program_ss(struct amdgpu_device *adev,
 242                                      int enable,
 243                                      int pll_id,
 244                                      int crtc_id,
 245                                      struct amdgpu_atom_ss *ss)
 246 {
 247         unsigned i;
 248         int index = GetIndexIntoMasterTable(COMMAND, EnableSpreadSpectrumOnPPLL);
 249         union atom_enable_ss args;
 250 
 251         if (enable) {
 252                 /* Don't mess with SS if percentage is 0 or external ss.
 253                  * SS is already disabled previously, and disabling it
 254                  * again can cause display problems if the pll is already
 255                  * programmed.
 256                  */
 257                 if (ss->percentage == 0)
 258                         return;
 259                 if (ss->type & ATOM_EXTERNAL_SS_MASK)
 260                         return;
 261         } else {
 262                 for (i = 0; i < adev->mode_info.num_crtc; i++) {
 263                         if (adev->mode_info.crtcs[i] &&
 264                             adev->mode_info.crtcs[i]->enabled &&
 265                             i != crtc_id &&
 266                             pll_id == adev->mode_info.crtcs[i]->pll_id) {
 267                                 /* one other crtc is using this pll don't turn
 268                                  * off spread spectrum as it might turn off
 269                                  * display on active crtc
 270                                  */
 271                                 return;
 272                         }
 273                 }
 274         }
 275 
 276         memset(&args, 0, sizeof(args));
 277 
 278         args.v3.usSpreadSpectrumAmountFrac = cpu_to_le16(0);
 279         args.v3.ucSpreadSpectrumType = ss->type & ATOM_SS_CENTRE_SPREAD_MODE_MASK;
 280         switch (pll_id) {
 281         case ATOM_PPLL1:
 282                 args.v3.ucSpreadSpectrumType |= ATOM_PPLL_SS_TYPE_V3_P1PLL;
 283                 break;
 284         case ATOM_PPLL2:
 285                 args.v3.ucSpreadSpectrumType |= ATOM_PPLL_SS_TYPE_V3_P2PLL;
 286                 break;
 287         case ATOM_DCPLL:
 288                 args.v3.ucSpreadSpectrumType |= ATOM_PPLL_SS_TYPE_V3_DCPLL;
 289                 break;
 290         case ATOM_PPLL_INVALID:
 291                 return;
 292         }
 293         args.v3.usSpreadSpectrumAmount = cpu_to_le16(ss->amount);
 294         args.v3.usSpreadSpectrumStep = cpu_to_le16(ss->step);
 295         args.v3.ucEnable = enable;
 296 
 297         amdgpu_atom_execute_table(adev->mode_info.atom_context, index, (uint32_t *)&args);
 298 }
 299 
 300 union adjust_pixel_clock {
 301         ADJUST_DISPLAY_PLL_PS_ALLOCATION v1;
 302         ADJUST_DISPLAY_PLL_PS_ALLOCATION_V3 v3;
 303 };
 304 
 305 static u32 amdgpu_atombios_crtc_adjust_pll(struct drm_crtc *crtc,
 306                                     struct drm_display_mode *mode)
 307 {
 308         struct amdgpu_crtc *amdgpu_crtc = to_amdgpu_crtc(crtc);
 309         struct drm_device *dev = crtc->dev;
 310         struct amdgpu_device *adev = dev->dev_private;
 311         struct drm_encoder *encoder = amdgpu_crtc->encoder;
 312         struct amdgpu_encoder *amdgpu_encoder = to_amdgpu_encoder(encoder);
 313         struct drm_connector *connector = amdgpu_get_connector_for_encoder(encoder);
 314         u32 adjusted_clock = mode->clock;
 315         int encoder_mode = amdgpu_atombios_encoder_get_encoder_mode(encoder);
 316         u32 dp_clock = mode->clock;
 317         u32 clock = mode->clock;
 318         int bpc = amdgpu_crtc->bpc;
 319         bool is_duallink = amdgpu_dig_monitor_is_duallink(encoder, mode->clock);
 320         union adjust_pixel_clock args;
 321         u8 frev, crev;
 322         int index;
 323 
 324         amdgpu_crtc->pll_flags = AMDGPU_PLL_USE_FRAC_FB_DIV;
 325 
 326         if ((amdgpu_encoder->devices & (ATOM_DEVICE_LCD_SUPPORT | ATOM_DEVICE_DFP_SUPPORT)) ||
 327             (amdgpu_encoder_get_dp_bridge_encoder_id(encoder) != ENCODER_OBJECT_ID_NONE)) {
 328                 if (connector) {
 329                         struct amdgpu_connector *amdgpu_connector = to_amdgpu_connector(connector);
 330                         struct amdgpu_connector_atom_dig *dig_connector =
 331                                 amdgpu_connector->con_priv;
 332 
 333                         dp_clock = dig_connector->dp_clock;
 334                 }
 335         }
 336 
 337         /* use recommended ref_div for ss */
 338         if (amdgpu_encoder->devices & (ATOM_DEVICE_LCD_SUPPORT)) {
 339                 if (amdgpu_crtc->ss_enabled) {
 340                         if (amdgpu_crtc->ss.refdiv) {
 341                                 amdgpu_crtc->pll_flags |= AMDGPU_PLL_USE_REF_DIV;
 342                                 amdgpu_crtc->pll_reference_div = amdgpu_crtc->ss.refdiv;
 343                                 amdgpu_crtc->pll_flags |= AMDGPU_PLL_USE_FRAC_FB_DIV;
 344                         }
 345                 }
 346         }
 347 
 348         /* DVO wants 2x pixel clock if the DVO chip is in 12 bit mode */
 349         if (amdgpu_encoder->encoder_id == ENCODER_OBJECT_ID_INTERNAL_KLDSCP_DVO1)
 350                 adjusted_clock = mode->clock * 2;
 351         if (amdgpu_encoder->active_device & (ATOM_DEVICE_TV_SUPPORT))
 352                 amdgpu_crtc->pll_flags |= AMDGPU_PLL_PREFER_CLOSEST_LOWER;
 353         if (amdgpu_encoder->devices & (ATOM_DEVICE_LCD_SUPPORT))
 354                 amdgpu_crtc->pll_flags |= AMDGPU_PLL_IS_LCD;
 355 
 356 
 357         /* adjust pll for deep color modes */
 358         if (encoder_mode == ATOM_ENCODER_MODE_HDMI) {
 359                 switch (bpc) {
 360                 case 8:
 361                 default:
 362                         break;
 363                 case 10:
 364                         clock = (clock * 5) / 4;
 365                         break;
 366                 case 12:
 367                         clock = (clock * 3) / 2;
 368                         break;
 369                 case 16:
 370                         clock = clock * 2;
 371                         break;
 372                 }
 373         }
 374 
 375         /* DCE3+ has an AdjustDisplayPll that will adjust the pixel clock
 376          * accordingly based on the encoder/transmitter to work around
 377          * special hw requirements.
 378          */
 379         index = GetIndexIntoMasterTable(COMMAND, AdjustDisplayPll);
 380         if (!amdgpu_atom_parse_cmd_header(adev->mode_info.atom_context, index, &frev,
 381                                    &crev))
 382                 return adjusted_clock;
 383 
 384         memset(&args, 0, sizeof(args));
 385 
 386         switch (frev) {
 387         case 1:
 388                 switch (crev) {
 389                 case 1:
 390                 case 2:
 391                         args.v1.usPixelClock = cpu_to_le16(clock / 10);
 392                         args.v1.ucTransmitterID = amdgpu_encoder->encoder_id;
 393                         args.v1.ucEncodeMode = encoder_mode;
 394                         if (amdgpu_crtc->ss_enabled && amdgpu_crtc->ss.percentage)
 395                                 args.v1.ucConfig |=
 396                                         ADJUST_DISPLAY_CONFIG_SS_ENABLE;
 397 
 398                         amdgpu_atom_execute_table(adev->mode_info.atom_context,
 399                                            index, (uint32_t *)&args);
 400                         adjusted_clock = le16_to_cpu(args.v1.usPixelClock) * 10;
 401                         break;
 402                 case 3:
 403                         args.v3.sInput.usPixelClock = cpu_to_le16(clock / 10);
 404                         args.v3.sInput.ucTransmitterID = amdgpu_encoder->encoder_id;
 405                         args.v3.sInput.ucEncodeMode = encoder_mode;
 406                         args.v3.sInput.ucDispPllConfig = 0;
 407                         if (amdgpu_crtc->ss_enabled && amdgpu_crtc->ss.percentage)
 408                                 args.v3.sInput.ucDispPllConfig |=
 409                                         DISPPLL_CONFIG_SS_ENABLE;
 410                         if (ENCODER_MODE_IS_DP(encoder_mode)) {
 411                                 args.v3.sInput.ucDispPllConfig |=
 412                                         DISPPLL_CONFIG_COHERENT_MODE;
 413                                 /* 16200 or 27000 */
 414                                 args.v3.sInput.usPixelClock = cpu_to_le16(dp_clock / 10);
 415                         } else if (amdgpu_encoder->devices & (ATOM_DEVICE_DFP_SUPPORT)) {
 416                                 struct amdgpu_encoder_atom_dig *dig = amdgpu_encoder->enc_priv;
 417                                 if (dig->coherent_mode)
 418                                         args.v3.sInput.ucDispPllConfig |=
 419                                                 DISPPLL_CONFIG_COHERENT_MODE;
 420                                 if (is_duallink)
 421                                         args.v3.sInput.ucDispPllConfig |=
 422                                                 DISPPLL_CONFIG_DUAL_LINK;
 423                         }
 424                         if (amdgpu_encoder_get_dp_bridge_encoder_id(encoder) !=
 425                             ENCODER_OBJECT_ID_NONE)
 426                                 args.v3.sInput.ucExtTransmitterID =
 427                                         amdgpu_encoder_get_dp_bridge_encoder_id(encoder);
 428                         else
 429                                 args.v3.sInput.ucExtTransmitterID = 0;
 430 
 431                         amdgpu_atom_execute_table(adev->mode_info.atom_context,
 432                                            index, (uint32_t *)&args);
 433                         adjusted_clock = le32_to_cpu(args.v3.sOutput.ulDispPllFreq) * 10;
 434                         if (args.v3.sOutput.ucRefDiv) {
 435                                 amdgpu_crtc->pll_flags |= AMDGPU_PLL_USE_FRAC_FB_DIV;
 436                                 amdgpu_crtc->pll_flags |= AMDGPU_PLL_USE_REF_DIV;
 437                                 amdgpu_crtc->pll_reference_div = args.v3.sOutput.ucRefDiv;
 438                         }
 439                         if (args.v3.sOutput.ucPostDiv) {
 440                                 amdgpu_crtc->pll_flags |= AMDGPU_PLL_USE_FRAC_FB_DIV;
 441                                 amdgpu_crtc->pll_flags |= AMDGPU_PLL_USE_POST_DIV;
 442                                 amdgpu_crtc->pll_post_div = args.v3.sOutput.ucPostDiv;
 443                         }
 444                         break;
 445                 default:
 446                         DRM_ERROR("Unknown table version %d %d\n", frev, crev);
 447                         return adjusted_clock;
 448                 }
 449                 break;
 450         default:
 451                 DRM_ERROR("Unknown table version %d %d\n", frev, crev);
 452                 return adjusted_clock;
 453         }
 454 
 455         return adjusted_clock;
 456 }
 457 
 458 union set_pixel_clock {
 459         SET_PIXEL_CLOCK_PS_ALLOCATION base;
 460         PIXEL_CLOCK_PARAMETERS v1;
 461         PIXEL_CLOCK_PARAMETERS_V2 v2;
 462         PIXEL_CLOCK_PARAMETERS_V3 v3;
 463         PIXEL_CLOCK_PARAMETERS_V5 v5;
 464         PIXEL_CLOCK_PARAMETERS_V6 v6;
 465         PIXEL_CLOCK_PARAMETERS_V7 v7;
 466 };
 467 
 468 /* on DCE5, make sure the voltage is high enough to support the
 469  * required disp clk.
 470  */
 471 void amdgpu_atombios_crtc_set_disp_eng_pll(struct amdgpu_device *adev,
 472                                            u32 dispclk)
 473 {
 474         u8 frev, crev;
 475         int index;
 476         union set_pixel_clock args;
 477 
 478         memset(&args, 0, sizeof(args));
 479 
 480         index = GetIndexIntoMasterTable(COMMAND, SetPixelClock);
 481         if (!amdgpu_atom_parse_cmd_header(adev->mode_info.atom_context, index, &frev,
 482                                    &crev))
 483                 return;
 484 
 485         switch (frev) {
 486         case 1:
 487                 switch (crev) {
 488                 case 5:
 489                         /* if the default dcpll clock is specified,
 490                          * SetPixelClock provides the dividers
 491                          */
 492                         args.v5.ucCRTC = ATOM_CRTC_INVALID;
 493                         args.v5.usPixelClock = cpu_to_le16(dispclk);
 494                         args.v5.ucPpll = ATOM_DCPLL;
 495                         break;
 496                 case 6:
 497                         /* if the default dcpll clock is specified,
 498                          * SetPixelClock provides the dividers
 499                          */
 500                         args.v6.ulDispEngClkFreq = cpu_to_le32(dispclk);
 501                         if (adev->asic_type == CHIP_TAHITI ||
 502                             adev->asic_type == CHIP_PITCAIRN ||
 503                             adev->asic_type == CHIP_VERDE ||
 504                             adev->asic_type == CHIP_OLAND)
 505                                 args.v6.ucPpll = ATOM_PPLL0;
 506                         else
 507                                 args.v6.ucPpll = ATOM_EXT_PLL1;
 508                         break;
 509                 default:
 510                         DRM_ERROR("Unknown table version %d %d\n", frev, crev);
 511                         return;
 512                 }
 513                 break;
 514         default:
 515                 DRM_ERROR("Unknown table version %d %d\n", frev, crev);
 516                 return;
 517         }
 518         amdgpu_atom_execute_table(adev->mode_info.atom_context, index, (uint32_t *)&args);
 519 }
 520 
 521 union set_dce_clock {
 522         SET_DCE_CLOCK_PS_ALLOCATION_V1_1 v1_1;
 523         SET_DCE_CLOCK_PS_ALLOCATION_V2_1 v2_1;
 524 };
 525 
 526 u32 amdgpu_atombios_crtc_set_dce_clock(struct amdgpu_device *adev,
 527                                        u32 freq, u8 clk_type, u8 clk_src)
 528 {
 529         u8 frev, crev;
 530         int index;
 531         union set_dce_clock args;
 532         u32 ret_freq = 0;
 533 
 534         memset(&args, 0, sizeof(args));
 535 
 536         index = GetIndexIntoMasterTable(COMMAND, SetDCEClock);
 537         if (!amdgpu_atom_parse_cmd_header(adev->mode_info.atom_context, index, &frev,
 538                                    &crev))
 539                 return 0;
 540 
 541         switch (frev) {
 542         case 2:
 543                 switch (crev) {
 544                 case 1:
 545                         args.v2_1.asParam.ulDCEClkFreq = cpu_to_le32(freq); /* 10kHz units */
 546                         args.v2_1.asParam.ucDCEClkType = clk_type;
 547                         args.v2_1.asParam.ucDCEClkSrc = clk_src;
 548                         amdgpu_atom_execute_table(adev->mode_info.atom_context, index, (uint32_t *)&args);
 549                         ret_freq = le32_to_cpu(args.v2_1.asParam.ulDCEClkFreq) * 10;
 550                         break;
 551                 default:
 552                         DRM_ERROR("Unknown table version %d %d\n", frev, crev);
 553                         return 0;
 554                 }
 555                 break;
 556         default:
 557                 DRM_ERROR("Unknown table version %d %d\n", frev, crev);
 558                 return 0;
 559         }
 560 
 561         return ret_freq;
 562 }
 563 
 564 static bool is_pixel_clock_source_from_pll(u32 encoder_mode, int pll_id)
 565 {
 566         if (ENCODER_MODE_IS_DP(encoder_mode)) {
 567                 if (pll_id < ATOM_EXT_PLL1)
 568                         return true;
 569                 else
 570                         return false;
 571         } else {
 572                 return true;
 573         }
 574 }
 575 
 576 void amdgpu_atombios_crtc_program_pll(struct drm_crtc *crtc,
 577                                       u32 crtc_id,
 578                                       int pll_id,
 579                                       u32 encoder_mode,
 580                                       u32 encoder_id,
 581                                       u32 clock,
 582                                       u32 ref_div,
 583                                       u32 fb_div,
 584                                       u32 frac_fb_div,
 585                                       u32 post_div,
 586                                       int bpc,
 587                                       bool ss_enabled,
 588                                       struct amdgpu_atom_ss *ss)
 589 {
 590         struct drm_device *dev = crtc->dev;
 591         struct amdgpu_device *adev = dev->dev_private;
 592         u8 frev, crev;
 593         int index = GetIndexIntoMasterTable(COMMAND, SetPixelClock);
 594         union set_pixel_clock args;
 595 
 596         memset(&args, 0, sizeof(args));
 597 
 598         if (!amdgpu_atom_parse_cmd_header(adev->mode_info.atom_context, index, &frev,
 599                                    &crev))
 600                 return;
 601 
 602         switch (frev) {
 603         case 1:
 604                 switch (crev) {
 605                 case 1:
 606                         if (clock == ATOM_DISABLE)
 607                                 return;
 608                         args.v1.usPixelClock = cpu_to_le16(clock / 10);
 609                         args.v1.usRefDiv = cpu_to_le16(ref_div);
 610                         args.v1.usFbDiv = cpu_to_le16(fb_div);
 611                         args.v1.ucFracFbDiv = frac_fb_div;
 612                         args.v1.ucPostDiv = post_div;
 613                         args.v1.ucPpll = pll_id;
 614                         args.v1.ucCRTC = crtc_id;
 615                         args.v1.ucRefDivSrc = 1;
 616                         break;
 617                 case 2:
 618                         args.v2.usPixelClock = cpu_to_le16(clock / 10);
 619                         args.v2.usRefDiv = cpu_to_le16(ref_div);
 620                         args.v2.usFbDiv = cpu_to_le16(fb_div);
 621                         args.v2.ucFracFbDiv = frac_fb_div;
 622                         args.v2.ucPostDiv = post_div;
 623                         args.v2.ucPpll = pll_id;
 624                         args.v2.ucCRTC = crtc_id;
 625                         args.v2.ucRefDivSrc = 1;
 626                         break;
 627                 case 3:
 628                         args.v3.usPixelClock = cpu_to_le16(clock / 10);
 629                         args.v3.usRefDiv = cpu_to_le16(ref_div);
 630                         args.v3.usFbDiv = cpu_to_le16(fb_div);
 631                         args.v3.ucFracFbDiv = frac_fb_div;
 632                         args.v3.ucPostDiv = post_div;
 633                         args.v3.ucPpll = pll_id;
 634                         if (crtc_id == ATOM_CRTC2)
 635                                 args.v3.ucMiscInfo = PIXEL_CLOCK_MISC_CRTC_SEL_CRTC2;
 636                         else
 637                                 args.v3.ucMiscInfo = PIXEL_CLOCK_MISC_CRTC_SEL_CRTC1;
 638                         if (ss_enabled && (ss->type & ATOM_EXTERNAL_SS_MASK))
 639                                 args.v3.ucMiscInfo |= PIXEL_CLOCK_MISC_REF_DIV_SRC;
 640                         args.v3.ucTransmitterId = encoder_id;
 641                         args.v3.ucEncoderMode = encoder_mode;
 642                         break;
 643                 case 5:
 644                         args.v5.ucCRTC = crtc_id;
 645                         args.v5.usPixelClock = cpu_to_le16(clock / 10);
 646                         args.v5.ucRefDiv = ref_div;
 647                         args.v5.usFbDiv = cpu_to_le16(fb_div);
 648                         args.v5.ulFbDivDecFrac = cpu_to_le32(frac_fb_div * 100000);
 649                         args.v5.ucPostDiv = post_div;
 650                         args.v5.ucMiscInfo = 0; /* HDMI depth, etc. */
 651                         if ((ss_enabled && (ss->type & ATOM_EXTERNAL_SS_MASK)) &&
 652                             (pll_id < ATOM_EXT_PLL1))
 653                                 args.v5.ucMiscInfo |= PIXEL_CLOCK_V5_MISC_REF_DIV_SRC;
 654                         if (encoder_mode == ATOM_ENCODER_MODE_HDMI) {
 655                                 switch (bpc) {
 656                                 case 8:
 657                                 default:
 658                                         args.v5.ucMiscInfo |= PIXEL_CLOCK_V5_MISC_HDMI_24BPP;
 659                                         break;
 660                                 case 10:
 661                                         /* yes this is correct, the atom define is wrong */
 662                                         args.v5.ucMiscInfo |= PIXEL_CLOCK_V5_MISC_HDMI_32BPP;
 663                                         break;
 664                                 case 12:
 665                                         /* yes this is correct, the atom define is wrong */
 666                                         args.v5.ucMiscInfo |= PIXEL_CLOCK_V5_MISC_HDMI_30BPP;
 667                                         break;
 668                                 }
 669                         }
 670                         args.v5.ucTransmitterID = encoder_id;
 671                         args.v5.ucEncoderMode = encoder_mode;
 672                         args.v5.ucPpll = pll_id;
 673                         break;
 674                 case 6:
 675                         args.v6.ulDispEngClkFreq = cpu_to_le32(crtc_id << 24 | clock / 10);
 676                         args.v6.ucRefDiv = ref_div;
 677                         args.v6.usFbDiv = cpu_to_le16(fb_div);
 678                         args.v6.ulFbDivDecFrac = cpu_to_le32(frac_fb_div * 100000);
 679                         args.v6.ucPostDiv = post_div;
 680                         args.v6.ucMiscInfo = 0; /* HDMI depth, etc. */
 681                         if ((ss_enabled && (ss->type & ATOM_EXTERNAL_SS_MASK)) &&
 682                             (pll_id < ATOM_EXT_PLL1) &&
 683                             !is_pixel_clock_source_from_pll(encoder_mode, pll_id))
 684                                 args.v6.ucMiscInfo |= PIXEL_CLOCK_V6_MISC_REF_DIV_SRC;
 685                         if (encoder_mode == ATOM_ENCODER_MODE_HDMI) {
 686                                 switch (bpc) {
 687                                 case 8:
 688                                 default:
 689                                         args.v6.ucMiscInfo |= PIXEL_CLOCK_V6_MISC_HDMI_24BPP;
 690                                         break;
 691                                 case 10:
 692                                         args.v6.ucMiscInfo |= PIXEL_CLOCK_V6_MISC_HDMI_30BPP_V6;
 693                                         break;
 694                                 case 12:
 695                                         args.v6.ucMiscInfo |= PIXEL_CLOCK_V6_MISC_HDMI_36BPP_V6;
 696                                         break;
 697                                 case 16:
 698                                         args.v6.ucMiscInfo |= PIXEL_CLOCK_V6_MISC_HDMI_48BPP;
 699                                         break;
 700                                 }
 701                         }
 702                         args.v6.ucTransmitterID = encoder_id;
 703                         args.v6.ucEncoderMode = encoder_mode;
 704                         args.v6.ucPpll = pll_id;
 705                         break;
 706                 case 7:
 707                         args.v7.ulPixelClock = cpu_to_le32(clock * 10); /* 100 hz units */
 708                         args.v7.ucMiscInfo = 0;
 709                         if ((encoder_mode == ATOM_ENCODER_MODE_DVI) &&
 710                             (clock > 165000))
 711                                 args.v7.ucMiscInfo |= PIXEL_CLOCK_V7_MISC_DVI_DUALLINK_EN;
 712                         args.v7.ucCRTC = crtc_id;
 713                         if (encoder_mode == ATOM_ENCODER_MODE_HDMI) {
 714                                 switch (bpc) {
 715                                 case 8:
 716                                 default:
 717                                         args.v7.ucDeepColorRatio = PIXEL_CLOCK_V7_DEEPCOLOR_RATIO_DIS;
 718                                         break;
 719                                 case 10:
 720                                         args.v7.ucDeepColorRatio = PIXEL_CLOCK_V7_DEEPCOLOR_RATIO_5_4;
 721                                         break;
 722                                 case 12:
 723                                         args.v7.ucDeepColorRatio = PIXEL_CLOCK_V7_DEEPCOLOR_RATIO_3_2;
 724                                         break;
 725                                 case 16:
 726                                         args.v7.ucDeepColorRatio = PIXEL_CLOCK_V7_DEEPCOLOR_RATIO_2_1;
 727                                         break;
 728                                 }
 729                         }
 730                         args.v7.ucTransmitterID = encoder_id;
 731                         args.v7.ucEncoderMode = encoder_mode;
 732                         args.v7.ucPpll = pll_id;
 733                         break;
 734                 default:
 735                         DRM_ERROR("Unknown table version %d %d\n", frev, crev);
 736                         return;
 737                 }
 738                 break;
 739         default:
 740                 DRM_ERROR("Unknown table version %d %d\n", frev, crev);
 741                 return;
 742         }
 743 
 744         amdgpu_atom_execute_table(adev->mode_info.atom_context, index, (uint32_t *)&args);
 745 }
 746 
 747 int amdgpu_atombios_crtc_prepare_pll(struct drm_crtc *crtc,
 748                               struct drm_display_mode *mode)
 749 {
 750         struct amdgpu_crtc *amdgpu_crtc = to_amdgpu_crtc(crtc);
 751         struct drm_device *dev = crtc->dev;
 752         struct amdgpu_device *adev = dev->dev_private;
 753         struct amdgpu_encoder *amdgpu_encoder =
 754                 to_amdgpu_encoder(amdgpu_crtc->encoder);
 755         int encoder_mode = amdgpu_atombios_encoder_get_encoder_mode(amdgpu_crtc->encoder);
 756 
 757         amdgpu_crtc->bpc = 8;
 758         amdgpu_crtc->ss_enabled = false;
 759 
 760         if ((amdgpu_encoder->active_device & (ATOM_DEVICE_LCD_SUPPORT | ATOM_DEVICE_DFP_SUPPORT)) ||
 761             (amdgpu_encoder_get_dp_bridge_encoder_id(amdgpu_crtc->encoder) != ENCODER_OBJECT_ID_NONE)) {
 762                 struct amdgpu_encoder_atom_dig *dig = amdgpu_encoder->enc_priv;
 763                 struct drm_connector *connector =
 764                         amdgpu_get_connector_for_encoder(amdgpu_crtc->encoder);
 765                 struct amdgpu_connector *amdgpu_connector =
 766                         to_amdgpu_connector(connector);
 767                 struct amdgpu_connector_atom_dig *dig_connector =
 768                         amdgpu_connector->con_priv;
 769                 int dp_clock;
 770 
 771                 /* Assign mode clock for hdmi deep color max clock limit check */
 772                 amdgpu_connector->pixelclock_for_modeset = mode->clock;
 773                 amdgpu_crtc->bpc = amdgpu_connector_get_monitor_bpc(connector);
 774 
 775                 switch (encoder_mode) {
 776                 case ATOM_ENCODER_MODE_DP_MST:
 777                 case ATOM_ENCODER_MODE_DP:
 778                         /* DP/eDP */
 779                         dp_clock = dig_connector->dp_clock / 10;
 780                         amdgpu_crtc->ss_enabled =
 781                                 amdgpu_atombios_get_asic_ss_info(adev, &amdgpu_crtc->ss,
 782                                                                  ASIC_INTERNAL_SS_ON_DP,
 783                                                                  dp_clock);
 784                         break;
 785                 case ATOM_ENCODER_MODE_LVDS:
 786                         amdgpu_crtc->ss_enabled =
 787                                 amdgpu_atombios_get_asic_ss_info(adev,
 788                                                                  &amdgpu_crtc->ss,
 789                                                                  dig->lcd_ss_id,
 790                                                                  mode->clock / 10);
 791                         break;
 792                 case ATOM_ENCODER_MODE_DVI:
 793                         amdgpu_crtc->ss_enabled =
 794                                 amdgpu_atombios_get_asic_ss_info(adev,
 795                                                                  &amdgpu_crtc->ss,
 796                                                                  ASIC_INTERNAL_SS_ON_TMDS,
 797                                                                  mode->clock / 10);
 798                         break;
 799                 case ATOM_ENCODER_MODE_HDMI:
 800                         amdgpu_crtc->ss_enabled =
 801                                 amdgpu_atombios_get_asic_ss_info(adev,
 802                                                                  &amdgpu_crtc->ss,
 803                                                                  ASIC_INTERNAL_SS_ON_HDMI,
 804                                                                  mode->clock / 10);
 805                         break;
 806                 default:
 807                         break;
 808                 }
 809         }
 810 
 811         /* adjust pixel clock as needed */
 812         amdgpu_crtc->adjusted_clock = amdgpu_atombios_crtc_adjust_pll(crtc, mode);
 813 
 814         return 0;
 815 }
 816 
 817 void amdgpu_atombios_crtc_set_pll(struct drm_crtc *crtc, struct drm_display_mode *mode)
 818 {
 819         struct amdgpu_crtc *amdgpu_crtc = to_amdgpu_crtc(crtc);
 820         struct drm_device *dev = crtc->dev;
 821         struct amdgpu_device *adev = dev->dev_private;
 822         struct amdgpu_encoder *amdgpu_encoder =
 823                 to_amdgpu_encoder(amdgpu_crtc->encoder);
 824         u32 pll_clock = mode->clock;
 825         u32 clock = mode->clock;
 826         u32 ref_div = 0, fb_div = 0, frac_fb_div = 0, post_div = 0;
 827         struct amdgpu_pll *pll;
 828         int encoder_mode = amdgpu_atombios_encoder_get_encoder_mode(amdgpu_crtc->encoder);
 829 
 830         /* pass the actual clock to amdgpu_atombios_crtc_program_pll for HDMI */
 831         if ((encoder_mode == ATOM_ENCODER_MODE_HDMI) &&
 832             (amdgpu_crtc->bpc > 8))
 833                 clock = amdgpu_crtc->adjusted_clock;
 834 
 835         switch (amdgpu_crtc->pll_id) {
 836         case ATOM_PPLL1:
 837                 pll = &adev->clock.ppll[0];
 838                 break;
 839         case ATOM_PPLL2:
 840                 pll = &adev->clock.ppll[1];
 841                 break;
 842         case ATOM_PPLL0:
 843         case ATOM_PPLL_INVALID:
 844         default:
 845                 pll = &adev->clock.ppll[2];
 846                 break;
 847         }
 848 
 849         /* update pll params */
 850         pll->flags = amdgpu_crtc->pll_flags;
 851         pll->reference_div = amdgpu_crtc->pll_reference_div;
 852         pll->post_div = amdgpu_crtc->pll_post_div;
 853 
 854         amdgpu_pll_compute(pll, amdgpu_crtc->adjusted_clock, &pll_clock,
 855                             &fb_div, &frac_fb_div, &ref_div, &post_div);
 856 
 857         amdgpu_atombios_crtc_program_ss(adev, ATOM_DISABLE, amdgpu_crtc->pll_id,
 858                                  amdgpu_crtc->crtc_id, &amdgpu_crtc->ss);
 859 
 860         amdgpu_atombios_crtc_program_pll(crtc, amdgpu_crtc->crtc_id, amdgpu_crtc->pll_id,
 861                                   encoder_mode, amdgpu_encoder->encoder_id, clock,
 862                                   ref_div, fb_div, frac_fb_div, post_div,
 863                                   amdgpu_crtc->bpc, amdgpu_crtc->ss_enabled, &amdgpu_crtc->ss);
 864 
 865         if (amdgpu_crtc->ss_enabled) {
 866                 /* calculate ss amount and step size */
 867                 u32 step_size;
 868                 u32 amount = (((fb_div * 10) + frac_fb_div) *
 869                               (u32)amdgpu_crtc->ss.percentage) /
 870                         (100 * (u32)amdgpu_crtc->ss.percentage_divider);
 871                 amdgpu_crtc->ss.amount = (amount / 10) & ATOM_PPLL_SS_AMOUNT_V2_FBDIV_MASK;
 872                 amdgpu_crtc->ss.amount |= ((amount - (amount / 10)) << ATOM_PPLL_SS_AMOUNT_V2_NFRAC_SHIFT) &
 873                         ATOM_PPLL_SS_AMOUNT_V2_NFRAC_MASK;
 874                 if (amdgpu_crtc->ss.type & ATOM_PPLL_SS_TYPE_V2_CENTRE_SPREAD)
 875                         step_size = (4 * amount * ref_div * ((u32)amdgpu_crtc->ss.rate * 2048)) /
 876                                 (125 * 25 * pll->reference_freq / 100);
 877                 else
 878                         step_size = (2 * amount * ref_div * ((u32)amdgpu_crtc->ss.rate * 2048)) /
 879                                 (125 * 25 * pll->reference_freq / 100);
 880                 amdgpu_crtc->ss.step = step_size;
 881 
 882                 amdgpu_atombios_crtc_program_ss(adev, ATOM_ENABLE, amdgpu_crtc->pll_id,
 883                                          amdgpu_crtc->crtc_id, &amdgpu_crtc->ss);
 884         }
 885 }
 886 

/* [<][>][^][v][top][bottom][index][help] */