linux/drivers/gpu/drm/radeon/atombios_crtc.c
<<
>>
Prefs
   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#include <drm/drmP.h>
  27#include <drm/drm_crtc_helper.h>
  28#include <drm/radeon_drm.h>
  29#include "radeon_fixed.h"
  30#include "radeon.h"
  31#include "atom.h"
  32#include "atom-bits.h"
  33
  34static void atombios_overscan_setup(struct drm_crtc *crtc,
  35                                    struct drm_display_mode *mode,
  36                                    struct drm_display_mode *adjusted_mode)
  37{
  38        struct drm_device *dev = crtc->dev;
  39        struct radeon_device *rdev = dev->dev_private;
  40        struct radeon_crtc *radeon_crtc = to_radeon_crtc(crtc);
  41        SET_CRTC_OVERSCAN_PS_ALLOCATION args;
  42        int index = GetIndexIntoMasterTable(COMMAND, SetCRTC_OverScan);
  43        int a1, a2;
  44
  45        memset(&args, 0, sizeof(args));
  46
  47        args.usOverscanRight = 0;
  48        args.usOverscanLeft = 0;
  49        args.usOverscanBottom = 0;
  50        args.usOverscanTop = 0;
  51        args.ucCRTC = radeon_crtc->crtc_id;
  52
  53        switch (radeon_crtc->rmx_type) {
  54        case RMX_CENTER:
  55                args.usOverscanTop = (adjusted_mode->crtc_vdisplay - mode->crtc_vdisplay) / 2;
  56                args.usOverscanBottom = (adjusted_mode->crtc_vdisplay - mode->crtc_vdisplay) / 2;
  57                args.usOverscanLeft = (adjusted_mode->crtc_hdisplay - mode->crtc_hdisplay) / 2;
  58                args.usOverscanRight = (adjusted_mode->crtc_hdisplay - mode->crtc_hdisplay) / 2;
  59                atom_execute_table(rdev->mode_info.atom_context, index, (uint32_t *)&args);
  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 = (adjusted_mode->crtc_hdisplay - (a2 / mode->crtc_vdisplay)) / 2;
  67                        args.usOverscanRight = (adjusted_mode->crtc_hdisplay - (a2 / mode->crtc_vdisplay)) / 2;
  68                } else if (a2 > a1) {
  69                        args.usOverscanLeft = (adjusted_mode->crtc_vdisplay - (a1 / mode->crtc_hdisplay)) / 2;
  70                        args.usOverscanRight = (adjusted_mode->crtc_vdisplay - (a1 / mode->crtc_hdisplay)) / 2;
  71                }
  72                atom_execute_table(rdev->mode_info.atom_context, index, (uint32_t *)&args);
  73                break;
  74        case RMX_FULL:
  75        default:
  76                args.usOverscanRight = 0;
  77                args.usOverscanLeft = 0;
  78                args.usOverscanBottom = 0;
  79                args.usOverscanTop = 0;
  80                atom_execute_table(rdev->mode_info.atom_context, index, (uint32_t *)&args);
  81                break;
  82        }
  83}
  84
  85static void atombios_scaler_setup(struct drm_crtc *crtc)
  86{
  87        struct drm_device *dev = crtc->dev;
  88        struct radeon_device *rdev = dev->dev_private;
  89        struct radeon_crtc *radeon_crtc = to_radeon_crtc(crtc);
  90        ENABLE_SCALER_PS_ALLOCATION args;
  91        int index = GetIndexIntoMasterTable(COMMAND, EnableScaler);
  92
  93        /* fixme - fill in enc_priv for atom dac */
  94        enum radeon_tv_std tv_std = TV_STD_NTSC;
  95        bool is_tv = false, is_cv = false;
  96        struct drm_encoder *encoder;
  97
  98        if (!ASIC_IS_AVIVO(rdev) && radeon_crtc->crtc_id)
  99                return;
 100
 101        list_for_each_entry(encoder, &dev->mode_config.encoder_list, head) {
 102                /* find tv std */
 103                if (encoder->crtc == crtc) {
 104                        struct radeon_encoder *radeon_encoder = to_radeon_encoder(encoder);
 105                        if (radeon_encoder->active_device & ATOM_DEVICE_TV_SUPPORT) {
 106                                struct radeon_encoder_atom_dac *tv_dac = radeon_encoder->enc_priv;
 107                                tv_std = tv_dac->tv_std;
 108                                is_tv = true;
 109                        }
 110                }
 111        }
 112
 113        memset(&args, 0, sizeof(args));
 114
 115        args.ucScaler = radeon_crtc->crtc_id;
 116
 117        if (is_tv) {
 118                switch (tv_std) {
 119                case TV_STD_NTSC:
 120                default:
 121                        args.ucTVStandard = ATOM_TV_NTSC;
 122                        break;
 123                case TV_STD_PAL:
 124                        args.ucTVStandard = ATOM_TV_PAL;
 125                        break;
 126                case TV_STD_PAL_M:
 127                        args.ucTVStandard = ATOM_TV_PALM;
 128                        break;
 129                case TV_STD_PAL_60:
 130                        args.ucTVStandard = ATOM_TV_PAL60;
 131                        break;
 132                case TV_STD_NTSC_J:
 133                        args.ucTVStandard = ATOM_TV_NTSCJ;
 134                        break;
 135                case TV_STD_SCART_PAL:
 136                        args.ucTVStandard = ATOM_TV_PAL; /* ??? */
 137                        break;
 138                case TV_STD_SECAM:
 139                        args.ucTVStandard = ATOM_TV_SECAM;
 140                        break;
 141                case TV_STD_PAL_CN:
 142                        args.ucTVStandard = ATOM_TV_PALCN;
 143                        break;
 144                }
 145                args.ucEnable = SCALER_ENABLE_MULTITAP_MODE;
 146        } else if (is_cv) {
 147                args.ucTVStandard = ATOM_TV_CV;
 148                args.ucEnable = SCALER_ENABLE_MULTITAP_MODE;
 149        } else {
 150                switch (radeon_crtc->rmx_type) {
 151                case RMX_FULL:
 152                        args.ucEnable = ATOM_SCALER_EXPANSION;
 153                        break;
 154                case RMX_CENTER:
 155                        args.ucEnable = ATOM_SCALER_CENTER;
 156                        break;
 157                case RMX_ASPECT:
 158                        args.ucEnable = ATOM_SCALER_EXPANSION;
 159                        break;
 160                default:
 161                        if (ASIC_IS_AVIVO(rdev))
 162                                args.ucEnable = ATOM_SCALER_DISABLE;
 163                        else
 164                                args.ucEnable = ATOM_SCALER_CENTER;
 165                        break;
 166                }
 167        }
 168        atom_execute_table(rdev->mode_info.atom_context, index, (uint32_t *)&args);
 169        if ((is_tv || is_cv)
 170            && rdev->family >= CHIP_RV515 && rdev->family <= CHIP_R580) {
 171                atom_rv515_force_tv_scaler(rdev, radeon_crtc);
 172        }
 173}
 174
 175static void atombios_lock_crtc(struct drm_crtc *crtc, int lock)
 176{
 177        struct radeon_crtc *radeon_crtc = to_radeon_crtc(crtc);
 178        struct drm_device *dev = crtc->dev;
 179        struct radeon_device *rdev = dev->dev_private;
 180        int index =
 181            GetIndexIntoMasterTable(COMMAND, UpdateCRTC_DoubleBufferRegisters);
 182        ENABLE_CRTC_PS_ALLOCATION args;
 183
 184        memset(&args, 0, sizeof(args));
 185
 186        args.ucCRTC = radeon_crtc->crtc_id;
 187        args.ucEnable = lock;
 188
 189        atom_execute_table(rdev->mode_info.atom_context, index, (uint32_t *)&args);
 190}
 191
 192static void atombios_enable_crtc(struct drm_crtc *crtc, int state)
 193{
 194        struct radeon_crtc *radeon_crtc = to_radeon_crtc(crtc);
 195        struct drm_device *dev = crtc->dev;
 196        struct radeon_device *rdev = dev->dev_private;
 197        int index = GetIndexIntoMasterTable(COMMAND, EnableCRTC);
 198        ENABLE_CRTC_PS_ALLOCATION args;
 199
 200        memset(&args, 0, sizeof(args));
 201
 202        args.ucCRTC = radeon_crtc->crtc_id;
 203        args.ucEnable = state;
 204
 205        atom_execute_table(rdev->mode_info.atom_context, index, (uint32_t *)&args);
 206}
 207
 208static void atombios_enable_crtc_memreq(struct drm_crtc *crtc, int state)
 209{
 210        struct radeon_crtc *radeon_crtc = to_radeon_crtc(crtc);
 211        struct drm_device *dev = crtc->dev;
 212        struct radeon_device *rdev = dev->dev_private;
 213        int index = GetIndexIntoMasterTable(COMMAND, EnableCRTCMemReq);
 214        ENABLE_CRTC_PS_ALLOCATION args;
 215
 216        memset(&args, 0, sizeof(args));
 217
 218        args.ucCRTC = radeon_crtc->crtc_id;
 219        args.ucEnable = state;
 220
 221        atom_execute_table(rdev->mode_info.atom_context, index, (uint32_t *)&args);
 222}
 223
 224static void atombios_blank_crtc(struct drm_crtc *crtc, int state)
 225{
 226        struct radeon_crtc *radeon_crtc = to_radeon_crtc(crtc);
 227        struct drm_device *dev = crtc->dev;
 228        struct radeon_device *rdev = dev->dev_private;
 229        int index = GetIndexIntoMasterTable(COMMAND, BlankCRTC);
 230        BLANK_CRTC_PS_ALLOCATION args;
 231
 232        memset(&args, 0, sizeof(args));
 233
 234        args.ucCRTC = radeon_crtc->crtc_id;
 235        args.ucBlanking = state;
 236
 237        atom_execute_table(rdev->mode_info.atom_context, index, (uint32_t *)&args);
 238}
 239
 240void atombios_crtc_dpms(struct drm_crtc *crtc, int mode)
 241{
 242        struct drm_device *dev = crtc->dev;
 243        struct radeon_device *rdev = dev->dev_private;
 244
 245        switch (mode) {
 246        case DRM_MODE_DPMS_ON:
 247                atombios_enable_crtc(crtc, 1);
 248                if (ASIC_IS_DCE3(rdev))
 249                        atombios_enable_crtc_memreq(crtc, 1);
 250                atombios_blank_crtc(crtc, 0);
 251                break;
 252        case DRM_MODE_DPMS_STANDBY:
 253        case DRM_MODE_DPMS_SUSPEND:
 254        case DRM_MODE_DPMS_OFF:
 255                atombios_blank_crtc(crtc, 1);
 256                if (ASIC_IS_DCE3(rdev))
 257                        atombios_enable_crtc_memreq(crtc, 0);
 258                atombios_enable_crtc(crtc, 0);
 259                break;
 260        }
 261
 262        if (mode != DRM_MODE_DPMS_OFF) {
 263                radeon_crtc_load_lut(crtc);
 264        }
 265}
 266
 267static void
 268atombios_set_crtc_dtd_timing(struct drm_crtc *crtc,
 269                             struct drm_display_mode *mode)
 270{
 271        struct radeon_crtc *radeon_crtc = to_radeon_crtc(crtc);
 272        struct drm_device *dev = crtc->dev;
 273        struct radeon_device *rdev = dev->dev_private;
 274        SET_CRTC_USING_DTD_TIMING_PARAMETERS args;
 275        int index = GetIndexIntoMasterTable(COMMAND, SetCRTC_UsingDTDTiming);
 276        u16 misc = 0;
 277
 278        memset(&args, 0, sizeof(args));
 279        args.usH_Size = cpu_to_le16(mode->crtc_hdisplay);
 280        args.usH_Blanking_Time =
 281                cpu_to_le16(mode->crtc_hblank_end - mode->crtc_hdisplay);
 282        args.usV_Size = cpu_to_le16(mode->crtc_vdisplay);
 283        args.usV_Blanking_Time =
 284            cpu_to_le16(mode->crtc_vblank_end - mode->crtc_vdisplay);
 285        args.usH_SyncOffset =
 286                cpu_to_le16(mode->crtc_hsync_start - mode->crtc_hdisplay);
 287        args.usH_SyncWidth =
 288                cpu_to_le16(mode->crtc_hsync_end - mode->crtc_hsync_start);
 289        args.usV_SyncOffset =
 290                cpu_to_le16(mode->crtc_vsync_start - mode->crtc_vdisplay);
 291        args.usV_SyncWidth =
 292                cpu_to_le16(mode->crtc_vsync_end - mode->crtc_vsync_start);
 293        /*args.ucH_Border = mode->hborder;*/
 294        /*args.ucV_Border = mode->vborder;*/
 295
 296        if (mode->flags & DRM_MODE_FLAG_NVSYNC)
 297                misc |= ATOM_VSYNC_POLARITY;
 298        if (mode->flags & DRM_MODE_FLAG_NHSYNC)
 299                misc |= ATOM_HSYNC_POLARITY;
 300        if (mode->flags & DRM_MODE_FLAG_CSYNC)
 301                misc |= ATOM_COMPOSITESYNC;
 302        if (mode->flags & DRM_MODE_FLAG_INTERLACE)
 303                misc |= ATOM_INTERLACE;
 304        if (mode->flags & DRM_MODE_FLAG_DBLSCAN)
 305                misc |= ATOM_DOUBLE_CLOCK_MODE;
 306
 307        args.susModeMiscInfo.usAccess = cpu_to_le16(misc);
 308        args.ucCRTC = radeon_crtc->crtc_id;
 309
 310        printk("executing set crtc dtd timing\n");
 311        atom_execute_table(rdev->mode_info.atom_context, index, (uint32_t *)&args);
 312}
 313
 314static void atombios_crtc_set_timing(struct drm_crtc *crtc,
 315                                     struct drm_display_mode *mode)
 316{
 317        struct radeon_crtc *radeon_crtc = to_radeon_crtc(crtc);
 318        struct drm_device *dev = crtc->dev;
 319        struct radeon_device *rdev = dev->dev_private;
 320        SET_CRTC_TIMING_PARAMETERS_PS_ALLOCATION args;
 321        int index = GetIndexIntoMasterTable(COMMAND, SetCRTC_Timing);
 322        u16 misc = 0;
 323
 324        memset(&args, 0, sizeof(args));
 325        args.usH_Total = cpu_to_le16(mode->crtc_htotal);
 326        args.usH_Disp = cpu_to_le16(mode->crtc_hdisplay);
 327        args.usH_SyncStart = cpu_to_le16(mode->crtc_hsync_start);
 328        args.usH_SyncWidth =
 329                cpu_to_le16(mode->crtc_hsync_end - mode->crtc_hsync_start);
 330        args.usV_Total = cpu_to_le16(mode->crtc_vtotal);
 331        args.usV_Disp = cpu_to_le16(mode->crtc_vdisplay);
 332        args.usV_SyncStart = cpu_to_le16(mode->crtc_vsync_start);
 333        args.usV_SyncWidth =
 334                cpu_to_le16(mode->crtc_vsync_end - mode->crtc_vsync_start);
 335
 336        if (mode->flags & DRM_MODE_FLAG_NVSYNC)
 337                misc |= ATOM_VSYNC_POLARITY;
 338        if (mode->flags & DRM_MODE_FLAG_NHSYNC)
 339                misc |= ATOM_HSYNC_POLARITY;
 340        if (mode->flags & DRM_MODE_FLAG_CSYNC)
 341                misc |= ATOM_COMPOSITESYNC;
 342        if (mode->flags & DRM_MODE_FLAG_INTERLACE)
 343                misc |= ATOM_INTERLACE;
 344        if (mode->flags & DRM_MODE_FLAG_DBLSCAN)
 345                misc |= ATOM_DOUBLE_CLOCK_MODE;
 346
 347        args.susModeMiscInfo.usAccess = cpu_to_le16(misc);
 348        args.ucCRTC = radeon_crtc->crtc_id;
 349
 350        printk("executing set crtc timing\n");
 351        atom_execute_table(rdev->mode_info.atom_context, index, (uint32_t *)&args);
 352}
 353
 354static void atombios_set_ss(struct drm_crtc *crtc, int enable)
 355{
 356        struct radeon_crtc *radeon_crtc = to_radeon_crtc(crtc);
 357        struct drm_device *dev = crtc->dev;
 358        struct radeon_device *rdev = dev->dev_private;
 359        struct drm_encoder *encoder = NULL;
 360        struct radeon_encoder *radeon_encoder = NULL;
 361        struct radeon_encoder_atom_dig *dig = NULL;
 362        int index = GetIndexIntoMasterTable(COMMAND, EnableSpreadSpectrumOnPPLL);
 363        ENABLE_SPREAD_SPECTRUM_ON_PPLL_PS_ALLOCATION args;
 364        ENABLE_LVDS_SS_PARAMETERS legacy_args;
 365        uint16_t percentage = 0;
 366        uint8_t type = 0, step = 0, delay = 0, range = 0;
 367
 368        list_for_each_entry(encoder, &dev->mode_config.encoder_list, head) {
 369                if (encoder->crtc == crtc) {
 370                        radeon_encoder = to_radeon_encoder(encoder);
 371                        /* only enable spread spectrum on LVDS */
 372                        if (radeon_encoder->devices & (ATOM_DEVICE_LCD_SUPPORT)) {
 373                                dig = radeon_encoder->enc_priv;
 374                                if (dig && dig->ss) {
 375                                        percentage = dig->ss->percentage;
 376                                        type = dig->ss->type;
 377                                        step = dig->ss->step;
 378                                        delay = dig->ss->delay;
 379                                        range = dig->ss->range;
 380                                } else if (enable)
 381                                        return;
 382                        } else if (enable)
 383                                return;
 384                        break;
 385                }
 386        }
 387
 388        if (!radeon_encoder)
 389                return;
 390
 391        if (ASIC_IS_AVIVO(rdev)) {
 392                memset(&args, 0, sizeof(args));
 393                args.usSpreadSpectrumPercentage = cpu_to_le16(percentage);
 394                args.ucSpreadSpectrumType = type;
 395                args.ucSpreadSpectrumStep = step;
 396                args.ucSpreadSpectrumDelay = delay;
 397                args.ucSpreadSpectrumRange = range;
 398                args.ucPpll = radeon_crtc->crtc_id ? ATOM_PPLL2 : ATOM_PPLL1;
 399                args.ucEnable = enable;
 400                atom_execute_table(rdev->mode_info.atom_context, index, (uint32_t *)&args);
 401        } else {
 402                memset(&legacy_args, 0, sizeof(legacy_args));
 403                legacy_args.usSpreadSpectrumPercentage = cpu_to_le16(percentage);
 404                legacy_args.ucSpreadSpectrumType = type;
 405                legacy_args.ucSpreadSpectrumStepSize_Delay = (step & 3) << 2;
 406                legacy_args.ucSpreadSpectrumStepSize_Delay |= (delay & 7) << 4;
 407                legacy_args.ucEnable = enable;
 408                atom_execute_table(rdev->mode_info.atom_context, index, (uint32_t *)&legacy_args);
 409        }
 410}
 411
 412void atombios_crtc_set_pll(struct drm_crtc *crtc, struct drm_display_mode *mode)
 413{
 414        struct radeon_crtc *radeon_crtc = to_radeon_crtc(crtc);
 415        struct drm_device *dev = crtc->dev;
 416        struct radeon_device *rdev = dev->dev_private;
 417        struct drm_encoder *encoder = NULL;
 418        struct radeon_encoder *radeon_encoder = NULL;
 419        uint8_t frev, crev;
 420        int index;
 421        SET_PIXEL_CLOCK_PS_ALLOCATION args;
 422        PIXEL_CLOCK_PARAMETERS *spc1_ptr;
 423        PIXEL_CLOCK_PARAMETERS_V2 *spc2_ptr;
 424        PIXEL_CLOCK_PARAMETERS_V3 *spc3_ptr;
 425        uint32_t pll_clock = mode->clock;
 426        uint32_t adjusted_clock;
 427        uint32_t ref_div = 0, fb_div = 0, frac_fb_div = 0, post_div = 0;
 428        struct radeon_pll *pll;
 429        int pll_flags = 0;
 430
 431        memset(&args, 0, sizeof(args));
 432
 433        if (ASIC_IS_AVIVO(rdev)) {
 434                if ((rdev->family == CHIP_RS600) ||
 435                    (rdev->family == CHIP_RS690) ||
 436                    (rdev->family == CHIP_RS740))
 437                        pll_flags |= (RADEON_PLL_USE_FRAC_FB_DIV |
 438                                      RADEON_PLL_PREFER_CLOSEST_LOWER);
 439
 440                if (ASIC_IS_DCE32(rdev) && mode->clock > 200000)        /* range limits??? */
 441                        pll_flags |= RADEON_PLL_PREFER_HIGH_FB_DIV;
 442                else
 443                        pll_flags |= RADEON_PLL_PREFER_LOW_REF_DIV;
 444        } else {
 445                pll_flags |= RADEON_PLL_LEGACY;
 446
 447                if (mode->clock > 200000)       /* range limits??? */
 448                        pll_flags |= RADEON_PLL_PREFER_HIGH_FB_DIV;
 449                else
 450                        pll_flags |= RADEON_PLL_PREFER_LOW_REF_DIV;
 451
 452        }
 453
 454        list_for_each_entry(encoder, &dev->mode_config.encoder_list, head) {
 455                if (encoder->crtc == crtc) {
 456                        if (!ASIC_IS_AVIVO(rdev)) {
 457                                if (encoder->encoder_type !=
 458                                    DRM_MODE_ENCODER_DAC)
 459                                        pll_flags |= RADEON_PLL_NO_ODD_POST_DIV;
 460                                if (!ASIC_IS_AVIVO(rdev)
 461                                    && (encoder->encoder_type ==
 462                                        DRM_MODE_ENCODER_LVDS))
 463                                        pll_flags |= RADEON_PLL_USE_REF_DIV;
 464                        }
 465                        radeon_encoder = to_radeon_encoder(encoder);
 466                        break;
 467                }
 468        }
 469
 470        /* DCE3+ has an AdjustDisplayPll that will adjust the pixel clock
 471         * accordingly based on the encoder/transmitter to work around
 472         * special hw requirements.
 473         */
 474        if (ASIC_IS_DCE3(rdev)) {
 475                ADJUST_DISPLAY_PLL_PS_ALLOCATION adjust_pll_args;
 476
 477                if (!encoder)
 478                        return;
 479
 480                memset(&adjust_pll_args, 0, sizeof(adjust_pll_args));
 481                adjust_pll_args.usPixelClock = cpu_to_le16(mode->clock / 10);
 482                adjust_pll_args.ucTransmitterID = radeon_encoder->encoder_id;
 483                adjust_pll_args.ucEncodeMode = atombios_get_encoder_mode(encoder);
 484
 485                index = GetIndexIntoMasterTable(COMMAND, AdjustDisplayPll);
 486                atom_execute_table(rdev->mode_info.atom_context,
 487                                   index, (uint32_t *)&adjust_pll_args);
 488                adjusted_clock = le16_to_cpu(adjust_pll_args.usPixelClock) * 10;
 489        } else {
 490                /* DVO wants 2x pixel clock if the DVO chip is in 12 bit mode */
 491                if (ASIC_IS_AVIVO(rdev) &&
 492                    (radeon_encoder->encoder_id == ENCODER_OBJECT_ID_INTERNAL_KLDSCP_DVO1))
 493                        adjusted_clock = mode->clock * 2;
 494                else
 495                        adjusted_clock = mode->clock;
 496        }
 497
 498        if (radeon_crtc->crtc_id == 0)
 499                pll = &rdev->clock.p1pll;
 500        else
 501                pll = &rdev->clock.p2pll;
 502
 503        radeon_compute_pll(pll, adjusted_clock, &pll_clock, &fb_div, &frac_fb_div,
 504                           &ref_div, &post_div, pll_flags);
 505
 506        index = GetIndexIntoMasterTable(COMMAND, SetPixelClock);
 507        atom_parse_cmd_header(rdev->mode_info.atom_context, index, &frev,
 508                              &crev);
 509
 510        switch (frev) {
 511        case 1:
 512                switch (crev) {
 513                case 1:
 514                        spc1_ptr = (PIXEL_CLOCK_PARAMETERS *) & args.sPCLKInput;
 515                        spc1_ptr->usPixelClock = cpu_to_le16(mode->clock / 10);
 516                        spc1_ptr->usRefDiv = cpu_to_le16(ref_div);
 517                        spc1_ptr->usFbDiv = cpu_to_le16(fb_div);
 518                        spc1_ptr->ucFracFbDiv = frac_fb_div;
 519                        spc1_ptr->ucPostDiv = post_div;
 520                        spc1_ptr->ucPpll =
 521                            radeon_crtc->crtc_id ? ATOM_PPLL2 : ATOM_PPLL1;
 522                        spc1_ptr->ucCRTC = radeon_crtc->crtc_id;
 523                        spc1_ptr->ucRefDivSrc = 1;
 524                        break;
 525                case 2:
 526                        spc2_ptr =
 527                            (PIXEL_CLOCK_PARAMETERS_V2 *) & args.sPCLKInput;
 528                        spc2_ptr->usPixelClock = cpu_to_le16(mode->clock / 10);
 529                        spc2_ptr->usRefDiv = cpu_to_le16(ref_div);
 530                        spc2_ptr->usFbDiv = cpu_to_le16(fb_div);
 531                        spc2_ptr->ucFracFbDiv = frac_fb_div;
 532                        spc2_ptr->ucPostDiv = post_div;
 533                        spc2_ptr->ucPpll =
 534                            radeon_crtc->crtc_id ? ATOM_PPLL2 : ATOM_PPLL1;
 535                        spc2_ptr->ucCRTC = radeon_crtc->crtc_id;
 536                        spc2_ptr->ucRefDivSrc = 1;
 537                        break;
 538                case 3:
 539                        if (!encoder)
 540                                return;
 541                        spc3_ptr =
 542                            (PIXEL_CLOCK_PARAMETERS_V3 *) & args.sPCLKInput;
 543                        spc3_ptr->usPixelClock = cpu_to_le16(mode->clock / 10);
 544                        spc3_ptr->usRefDiv = cpu_to_le16(ref_div);
 545                        spc3_ptr->usFbDiv = cpu_to_le16(fb_div);
 546                        spc3_ptr->ucFracFbDiv = frac_fb_div;
 547                        spc3_ptr->ucPostDiv = post_div;
 548                        spc3_ptr->ucPpll =
 549                            radeon_crtc->crtc_id ? ATOM_PPLL2 : ATOM_PPLL1;
 550                        spc3_ptr->ucMiscInfo = (radeon_crtc->crtc_id << 2);
 551                        spc3_ptr->ucTransmitterId = radeon_encoder->encoder_id;
 552                        spc3_ptr->ucEncoderMode =
 553                            atombios_get_encoder_mode(encoder);
 554                        break;
 555                default:
 556                        DRM_ERROR("Unknown table version %d %d\n", frev, crev);
 557                        return;
 558                }
 559                break;
 560        default:
 561                DRM_ERROR("Unknown table version %d %d\n", frev, crev);
 562                return;
 563        }
 564
 565        printk("executing set pll\n");
 566        atom_execute_table(rdev->mode_info.atom_context, index, (uint32_t *)&args);
 567}
 568
 569int atombios_crtc_set_base(struct drm_crtc *crtc, int x, int y,
 570                           struct drm_framebuffer *old_fb)
 571{
 572        struct radeon_crtc *radeon_crtc = to_radeon_crtc(crtc);
 573        struct drm_device *dev = crtc->dev;
 574        struct radeon_device *rdev = dev->dev_private;
 575        struct radeon_framebuffer *radeon_fb;
 576        struct drm_gem_object *obj;
 577        struct drm_radeon_gem_object *obj_priv;
 578        uint64_t fb_location;
 579        uint32_t fb_format, fb_pitch_pixels, tiling_flags;
 580
 581        if (!crtc->fb)
 582                return -EINVAL;
 583
 584        radeon_fb = to_radeon_framebuffer(crtc->fb);
 585
 586        obj = radeon_fb->obj;
 587        obj_priv = obj->driver_private;
 588
 589        if (radeon_gem_object_pin(obj, RADEON_GEM_DOMAIN_VRAM, &fb_location)) {
 590                return -EINVAL;
 591        }
 592
 593        switch (crtc->fb->bits_per_pixel) {
 594        case 8:
 595                fb_format =
 596                    AVIVO_D1GRPH_CONTROL_DEPTH_8BPP |
 597                    AVIVO_D1GRPH_CONTROL_8BPP_INDEXED;
 598                break;
 599        case 15:
 600                fb_format =
 601                    AVIVO_D1GRPH_CONTROL_DEPTH_16BPP |
 602                    AVIVO_D1GRPH_CONTROL_16BPP_ARGB1555;
 603                break;
 604        case 16:
 605                fb_format =
 606                    AVIVO_D1GRPH_CONTROL_DEPTH_16BPP |
 607                    AVIVO_D1GRPH_CONTROL_16BPP_RGB565;
 608                break;
 609        case 24:
 610        case 32:
 611                fb_format =
 612                    AVIVO_D1GRPH_CONTROL_DEPTH_32BPP |
 613                    AVIVO_D1GRPH_CONTROL_32BPP_ARGB8888;
 614                break;
 615        default:
 616                DRM_ERROR("Unsupported screen depth %d\n",
 617                          crtc->fb->bits_per_pixel);
 618                return -EINVAL;
 619        }
 620
 621        radeon_object_get_tiling_flags(obj->driver_private,
 622                                       &tiling_flags, NULL);
 623        if (tiling_flags & RADEON_TILING_MACRO)
 624                fb_format |= AVIVO_D1GRPH_MACRO_ADDRESS_MODE;
 625
 626        if (tiling_flags & RADEON_TILING_MICRO)
 627                fb_format |= AVIVO_D1GRPH_TILED;
 628
 629        if (radeon_crtc->crtc_id == 0)
 630                WREG32(AVIVO_D1VGA_CONTROL, 0);
 631        else
 632                WREG32(AVIVO_D2VGA_CONTROL, 0);
 633
 634        if (rdev->family >= CHIP_RV770) {
 635                if (radeon_crtc->crtc_id) {
 636                        WREG32(R700_D2GRPH_PRIMARY_SURFACE_ADDRESS_HIGH, 0);
 637                        WREG32(R700_D2GRPH_SECONDARY_SURFACE_ADDRESS_HIGH, 0);
 638                } else {
 639                        WREG32(R700_D1GRPH_PRIMARY_SURFACE_ADDRESS_HIGH, 0);
 640                        WREG32(R700_D1GRPH_SECONDARY_SURFACE_ADDRESS_HIGH, 0);
 641                }
 642        }
 643        WREG32(AVIVO_D1GRPH_PRIMARY_SURFACE_ADDRESS + radeon_crtc->crtc_offset,
 644               (u32) fb_location);
 645        WREG32(AVIVO_D1GRPH_SECONDARY_SURFACE_ADDRESS +
 646               radeon_crtc->crtc_offset, (u32) fb_location);
 647        WREG32(AVIVO_D1GRPH_CONTROL + radeon_crtc->crtc_offset, fb_format);
 648
 649        WREG32(AVIVO_D1GRPH_SURFACE_OFFSET_X + radeon_crtc->crtc_offset, 0);
 650        WREG32(AVIVO_D1GRPH_SURFACE_OFFSET_Y + radeon_crtc->crtc_offset, 0);
 651        WREG32(AVIVO_D1GRPH_X_START + radeon_crtc->crtc_offset, 0);
 652        WREG32(AVIVO_D1GRPH_Y_START + radeon_crtc->crtc_offset, 0);
 653        WREG32(AVIVO_D1GRPH_X_END + radeon_crtc->crtc_offset, crtc->fb->width);
 654        WREG32(AVIVO_D1GRPH_Y_END + radeon_crtc->crtc_offset, crtc->fb->height);
 655
 656        fb_pitch_pixels = crtc->fb->pitch / (crtc->fb->bits_per_pixel / 8);
 657        WREG32(AVIVO_D1GRPH_PITCH + radeon_crtc->crtc_offset, fb_pitch_pixels);
 658        WREG32(AVIVO_D1GRPH_ENABLE + radeon_crtc->crtc_offset, 1);
 659
 660        WREG32(AVIVO_D1MODE_DESKTOP_HEIGHT + radeon_crtc->crtc_offset,
 661               crtc->mode.vdisplay);
 662        x &= ~3;
 663        y &= ~1;
 664        WREG32(AVIVO_D1MODE_VIEWPORT_START + radeon_crtc->crtc_offset,
 665               (x << 16) | y);
 666        WREG32(AVIVO_D1MODE_VIEWPORT_SIZE + radeon_crtc->crtc_offset,
 667               (crtc->mode.hdisplay << 16) | crtc->mode.vdisplay);
 668
 669        if (crtc->mode.flags & DRM_MODE_FLAG_INTERLACE)
 670                WREG32(AVIVO_D1MODE_DATA_FORMAT + radeon_crtc->crtc_offset,
 671                       AVIVO_D1MODE_INTERLEAVE_EN);
 672        else
 673                WREG32(AVIVO_D1MODE_DATA_FORMAT + radeon_crtc->crtc_offset, 0);
 674
 675        if (old_fb && old_fb != crtc->fb) {
 676                radeon_fb = to_radeon_framebuffer(old_fb);
 677                radeon_gem_object_unpin(radeon_fb->obj);
 678        }
 679
 680        /* Bytes per pixel may have changed */
 681        radeon_bandwidth_update(rdev);
 682
 683        return 0;
 684}
 685
 686int atombios_crtc_mode_set(struct drm_crtc *crtc,
 687                           struct drm_display_mode *mode,
 688                           struct drm_display_mode *adjusted_mode,
 689                           int x, int y, struct drm_framebuffer *old_fb)
 690{
 691        struct radeon_crtc *radeon_crtc = to_radeon_crtc(crtc);
 692        struct drm_device *dev = crtc->dev;
 693        struct radeon_device *rdev = dev->dev_private;
 694
 695        /* TODO color tiling */
 696
 697        atombios_set_ss(crtc, 0);
 698        atombios_crtc_set_pll(crtc, adjusted_mode);
 699        atombios_set_ss(crtc, 1);
 700        atombios_crtc_set_timing(crtc, adjusted_mode);
 701
 702        if (ASIC_IS_AVIVO(rdev))
 703                atombios_crtc_set_base(crtc, x, y, old_fb);
 704        else {
 705                if (radeon_crtc->crtc_id == 0)
 706                        atombios_set_crtc_dtd_timing(crtc, adjusted_mode);
 707                radeon_crtc_set_base(crtc, x, y, old_fb);
 708                radeon_legacy_atom_set_surface(crtc);
 709        }
 710        atombios_overscan_setup(crtc, mode, adjusted_mode);
 711        atombios_scaler_setup(crtc);
 712        return 0;
 713}
 714
 715static bool atombios_crtc_mode_fixup(struct drm_crtc *crtc,
 716                                     struct drm_display_mode *mode,
 717                                     struct drm_display_mode *adjusted_mode)
 718{
 719        if (!radeon_crtc_scaling_mode_fixup(crtc, mode, adjusted_mode))
 720                return false;
 721        return true;
 722}
 723
 724static void atombios_crtc_prepare(struct drm_crtc *crtc)
 725{
 726        atombios_crtc_dpms(crtc, DRM_MODE_DPMS_OFF);
 727        atombios_lock_crtc(crtc, 1);
 728}
 729
 730static void atombios_crtc_commit(struct drm_crtc *crtc)
 731{
 732        atombios_crtc_dpms(crtc, DRM_MODE_DPMS_ON);
 733        atombios_lock_crtc(crtc, 0);
 734}
 735
 736static const struct drm_crtc_helper_funcs atombios_helper_funcs = {
 737        .dpms = atombios_crtc_dpms,
 738        .mode_fixup = atombios_crtc_mode_fixup,
 739        .mode_set = atombios_crtc_mode_set,
 740        .mode_set_base = atombios_crtc_set_base,
 741        .prepare = atombios_crtc_prepare,
 742        .commit = atombios_crtc_commit,
 743        .load_lut = radeon_crtc_load_lut,
 744};
 745
 746void radeon_atombios_init_crtc(struct drm_device *dev,
 747                               struct radeon_crtc *radeon_crtc)
 748{
 749        if (radeon_crtc->crtc_id == 1)
 750                radeon_crtc->crtc_offset =
 751                    AVIVO_D2CRTC_H_TOTAL - AVIVO_D1CRTC_H_TOTAL;
 752        drm_crtc_helper_add(&radeon_crtc->base, &atombios_helper_funcs);
 753}
 754
lxr.linux.no kindly hosted by Redpill Linpro AS, provider of Linux consulting and operations services since 1995.