linux/drivers/gpu/drm/gma500/oaktrail_crtc.c
<<
>>
Prefs
   1/*
   2 * Copyright © 2009 Intel Corporation
   3 *
   4 * This program is free software; you can redistribute it and/or modify it
   5 * under the terms and conditions of the GNU General Public License,
   6 * version 2, as published by the Free Software Foundation.
   7 *
   8 * This program is distributed in the hope it will be useful, but WITHOUT
   9 * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
  10 * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License for
  11 * more details.
  12 *
  13 * You should have received a copy of the GNU General Public License along with
  14 * this program; if not, write to the Free Software Foundation, Inc.,
  15 * 51 Franklin St - Fifth Floor, Boston, MA 02110-1301 USA.
  16 */
  17
  18#include <linux/i2c.h>
  19#include <linux/pm_runtime.h>
  20
  21#include <drm/drmP.h>
  22#include "framebuffer.h"
  23#include "psb_drv.h"
  24#include "psb_intel_drv.h"
  25#include "psb_intel_reg.h"
  26#include "psb_intel_display.h"
  27#include "power.h"
  28
  29struct psb_intel_range_t {
  30        int min, max;
  31};
  32
  33struct oaktrail_limit_t {
  34        struct psb_intel_range_t dot, m, p1;
  35};
  36
  37struct oaktrail_clock_t {
  38        /* derived values */
  39        int dot;
  40        int m;
  41        int p1;
  42};
  43
  44#define MRST_LIMIT_LVDS_100L        0
  45#define MRST_LIMIT_LVDS_83          1
  46#define MRST_LIMIT_LVDS_100         2
  47
  48#define MRST_DOT_MIN              19750
  49#define MRST_DOT_MAX              120000
  50#define MRST_M_MIN_100L             20
  51#define MRST_M_MIN_100              10
  52#define MRST_M_MIN_83               12
  53#define MRST_M_MAX_100L             34
  54#define MRST_M_MAX_100              17
  55#define MRST_M_MAX_83               20
  56#define MRST_P1_MIN                 2
  57#define MRST_P1_MAX_0               7
  58#define MRST_P1_MAX_1               8
  59
  60static const struct oaktrail_limit_t oaktrail_limits[] = {
  61        {                       /* MRST_LIMIT_LVDS_100L */
  62         .dot = {.min = MRST_DOT_MIN, .max = MRST_DOT_MAX},
  63         .m = {.min = MRST_M_MIN_100L, .max = MRST_M_MAX_100L},
  64         .p1 = {.min = MRST_P1_MIN, .max = MRST_P1_MAX_1},
  65         },
  66        {                       /* MRST_LIMIT_LVDS_83L */
  67         .dot = {.min = MRST_DOT_MIN, .max = MRST_DOT_MAX},
  68         .m = {.min = MRST_M_MIN_83, .max = MRST_M_MAX_83},
  69         .p1 = {.min = MRST_P1_MIN, .max = MRST_P1_MAX_0},
  70         },
  71        {                       /* MRST_LIMIT_LVDS_100 */
  72         .dot = {.min = MRST_DOT_MIN, .max = MRST_DOT_MAX},
  73         .m = {.min = MRST_M_MIN_100, .max = MRST_M_MAX_100},
  74         .p1 = {.min = MRST_P1_MIN, .max = MRST_P1_MAX_1},
  75         },
  76};
  77
  78#define MRST_M_MIN          10
  79static const u32 oaktrail_m_converts[] = {
  80        0x2B, 0x15, 0x2A, 0x35, 0x1A, 0x0D, 0x26, 0x33, 0x19, 0x2C,
  81        0x36, 0x3B, 0x1D, 0x2E, 0x37, 0x1B, 0x2D, 0x16, 0x0B, 0x25,
  82        0x12, 0x09, 0x24, 0x32, 0x39, 0x1c,
  83};
  84
  85static const struct oaktrail_limit_t *oaktrail_limit(struct drm_crtc *crtc)
  86{
  87        const struct oaktrail_limit_t *limit = NULL;
  88        struct drm_device *dev = crtc->dev;
  89        struct drm_psb_private *dev_priv = dev->dev_private;
  90
  91        if (psb_intel_pipe_has_type(crtc, INTEL_OUTPUT_LVDS)
  92            || psb_intel_pipe_has_type(crtc, INTEL_OUTPUT_MIPI)) {
  93                switch (dev_priv->core_freq) {
  94                case 100:
  95                        limit = &oaktrail_limits[MRST_LIMIT_LVDS_100L];
  96                        break;
  97                case 166:
  98                        limit = &oaktrail_limits[MRST_LIMIT_LVDS_83];
  99                        break;
 100                case 200:
 101                        limit = &oaktrail_limits[MRST_LIMIT_LVDS_100];
 102                        break;
 103                }
 104        } else {
 105                limit = NULL;
 106                dev_err(dev->dev, "oaktrail_limit Wrong display type.\n");
 107        }
 108
 109        return limit;
 110}
 111
 112/** Derive the pixel clock for the given refclk and divisors for 8xx chips. */
 113static void oaktrail_clock(int refclk, struct oaktrail_clock_t *clock)
 114{
 115        clock->dot = (refclk * clock->m) / (14 * clock->p1);
 116}
 117
 118static void mrstPrintPll(char *prefix, struct oaktrail_clock_t *clock)
 119{
 120        pr_debug("%s: dotclock = %d,  m = %d, p1 = %d.\n",
 121             prefix, clock->dot, clock->m, clock->p1);
 122}
 123
 124/**
 125 * Returns a set of divisors for the desired target clock with the given refclk,
 126 * or FALSE.  Divisor values are the actual divisors for
 127 */
 128static bool
 129mrstFindBestPLL(struct drm_crtc *crtc, int target, int refclk,
 130                struct oaktrail_clock_t *best_clock)
 131{
 132        struct oaktrail_clock_t clock;
 133        const struct oaktrail_limit_t *limit = oaktrail_limit(crtc);
 134        int err = target;
 135
 136        memset(best_clock, 0, sizeof(*best_clock));
 137
 138        for (clock.m = limit->m.min; clock.m <= limit->m.max; clock.m++) {
 139                for (clock.p1 = limit->p1.min; clock.p1 <= limit->p1.max;
 140                     clock.p1++) {
 141                        int this_err;
 142
 143                        oaktrail_clock(refclk, &clock);
 144
 145                        this_err = abs(clock.dot - target);
 146                        if (this_err < err) {
 147                                *best_clock = clock;
 148                                err = this_err;
 149                        }
 150                }
 151        }
 152        dev_dbg(crtc->dev->dev, "mrstFindBestPLL err = %d.\n", err);
 153        return err != target;
 154}
 155
 156/**
 157 * Sets the power management mode of the pipe and plane.
 158 *
 159 * This code should probably grow support for turning the cursor off and back
 160 * on appropriately at the same time as we're turning the pipe off/on.
 161 */
 162static void oaktrail_crtc_dpms(struct drm_crtc *crtc, int mode)
 163{
 164        struct drm_device *dev = crtc->dev;
 165        struct drm_psb_private *dev_priv = dev->dev_private;
 166        struct psb_intel_crtc *psb_intel_crtc = to_psb_intel_crtc(crtc);
 167        int pipe = psb_intel_crtc->pipe;
 168        const struct psb_offset *map = &dev_priv->regmap[pipe];
 169        u32 temp;
 170
 171        if (pipe == 1) {
 172                oaktrail_crtc_hdmi_dpms(crtc, mode);
 173                return;
 174        }
 175
 176        if (!gma_power_begin(dev, true))
 177                return;
 178
 179        /* XXX: When our outputs are all unaware of DPMS modes other than off
 180         * and on, we should map those modes to DRM_MODE_DPMS_OFF in the CRTC.
 181         */
 182        switch (mode) {
 183        case DRM_MODE_DPMS_ON:
 184        case DRM_MODE_DPMS_STANDBY:
 185        case DRM_MODE_DPMS_SUSPEND:
 186                /* Enable the DPLL */
 187                temp = REG_READ(map->dpll);
 188                if ((temp & DPLL_VCO_ENABLE) == 0) {
 189                        REG_WRITE(map->dpll, temp);
 190                        REG_READ(map->dpll);
 191                        /* Wait for the clocks to stabilize. */
 192                        udelay(150);
 193                        REG_WRITE(map->dpll, temp | DPLL_VCO_ENABLE);
 194                        REG_READ(map->dpll);
 195                        /* Wait for the clocks to stabilize. */
 196                        udelay(150);
 197                        REG_WRITE(map->dpll, temp | DPLL_VCO_ENABLE);
 198                        REG_READ(map->dpll);
 199                        /* Wait for the clocks to stabilize. */
 200                        udelay(150);
 201                }
 202                /* Enable the pipe */
 203                temp = REG_READ(map->conf);
 204                if ((temp & PIPEACONF_ENABLE) == 0)
 205                        REG_WRITE(map->conf, temp | PIPEACONF_ENABLE);
 206                /* Enable the plane */
 207                temp = REG_READ(map->cntr);
 208                if ((temp & DISPLAY_PLANE_ENABLE) == 0) {
 209                        REG_WRITE(map->cntr,
 210                                  temp | DISPLAY_PLANE_ENABLE);
 211                        /* Flush the plane changes */
 212                        REG_WRITE(map->base, REG_READ(map->base));
 213                }
 214
 215                psb_intel_crtc_load_lut(crtc);
 216
 217                /* Give the overlay scaler a chance to enable
 218                   if it's on this pipe */
 219                /* psb_intel_crtc_dpms_video(crtc, true); TODO */
 220                break;
 221        case DRM_MODE_DPMS_OFF:
 222                /* Give the overlay scaler a chance to disable
 223                 * if it's on this pipe */
 224                /* psb_intel_crtc_dpms_video(crtc, FALSE); TODO */
 225
 226                /* Disable the VGA plane that we never use */
 227                REG_WRITE(VGACNTRL, VGA_DISP_DISABLE);
 228                /* Disable display plane */
 229                temp = REG_READ(map->cntr);
 230                if ((temp & DISPLAY_PLANE_ENABLE) != 0) {
 231                        REG_WRITE(map->cntr,
 232                                  temp & ~DISPLAY_PLANE_ENABLE);
 233                        /* Flush the plane changes */
 234                        REG_WRITE(map->base, REG_READ(map->base));
 235                        REG_READ(map->base);
 236                }
 237
 238                /* Next, disable display pipes */
 239                temp = REG_READ(map->conf);
 240                if ((temp & PIPEACONF_ENABLE) != 0) {
 241                        REG_WRITE(map->conf, temp & ~PIPEACONF_ENABLE);
 242                        REG_READ(map->conf);
 243                }
 244                /* Wait for for the pipe disable to take effect. */
 245                psb_intel_wait_for_vblank(dev);
 246
 247                temp = REG_READ(map->dpll);
 248                if ((temp & DPLL_VCO_ENABLE) != 0) {
 249                        REG_WRITE(map->dpll, temp & ~DPLL_VCO_ENABLE);
 250                        REG_READ(map->dpll);
 251                }
 252
 253                /* Wait for the clocks to turn off. */
 254                udelay(150);
 255                break;
 256        }
 257
 258        /*Set FIFO Watermarks*/
 259        REG_WRITE(DSPARB, 0x3FFF);
 260        REG_WRITE(DSPFW1, 0x3F88080A);
 261        REG_WRITE(DSPFW2, 0x0b060808);
 262        REG_WRITE(DSPFW3, 0x0);
 263        REG_WRITE(DSPFW4, 0x08030404);
 264        REG_WRITE(DSPFW5, 0x04040404);
 265        REG_WRITE(DSPFW6, 0x78);
 266        REG_WRITE(0x70400, REG_READ(0x70400) | 0x4000);
 267        /* Must write Bit 14 of the Chicken Bit Register */
 268
 269        gma_power_end(dev);
 270}
 271
 272/**
 273 * Return the pipe currently connected to the panel fitter,
 274 * or -1 if the panel fitter is not present or not in use
 275 */
 276static int oaktrail_panel_fitter_pipe(struct drm_device *dev)
 277{
 278        u32 pfit_control;
 279
 280        pfit_control = REG_READ(PFIT_CONTROL);
 281
 282        /* See if the panel fitter is in use */
 283        if ((pfit_control & PFIT_ENABLE) == 0)
 284                return -1;
 285        return (pfit_control >> 29) & 3;
 286}
 287
 288static int oaktrail_crtc_mode_set(struct drm_crtc *crtc,
 289                              struct drm_display_mode *mode,
 290                              struct drm_display_mode *adjusted_mode,
 291                              int x, int y,
 292                              struct drm_framebuffer *old_fb)
 293{
 294        struct drm_device *dev = crtc->dev;
 295        struct psb_intel_crtc *psb_intel_crtc = to_psb_intel_crtc(crtc);
 296        struct drm_psb_private *dev_priv = dev->dev_private;
 297        int pipe = psb_intel_crtc->pipe;
 298        const struct psb_offset *map = &dev_priv->regmap[pipe];
 299        int refclk = 0;
 300        struct oaktrail_clock_t clock;
 301        u32 dpll = 0, fp = 0, dspcntr, pipeconf;
 302        bool ok, is_sdvo = false;
 303        bool is_lvds = false;
 304        bool is_mipi = false;
 305        struct drm_mode_config *mode_config = &dev->mode_config;
 306        struct psb_intel_encoder *psb_intel_encoder = NULL;
 307        uint64_t scalingType = DRM_MODE_SCALE_FULLSCREEN;
 308        struct drm_connector *connector;
 309
 310        if (pipe == 1)
 311                return oaktrail_crtc_hdmi_mode_set(crtc, mode, adjusted_mode, x, y, old_fb);
 312
 313        if (!gma_power_begin(dev, true))
 314                return 0;
 315
 316        memcpy(&psb_intel_crtc->saved_mode,
 317                mode,
 318                sizeof(struct drm_display_mode));
 319        memcpy(&psb_intel_crtc->saved_adjusted_mode,
 320                adjusted_mode,
 321                sizeof(struct drm_display_mode));
 322
 323        list_for_each_entry(connector, &mode_config->connector_list, head) {
 324                if (!connector->encoder || connector->encoder->crtc != crtc)
 325                        continue;
 326
 327                psb_intel_encoder = psb_intel_attached_encoder(connector);
 328
 329                switch (psb_intel_encoder->type) {
 330                case INTEL_OUTPUT_LVDS:
 331                        is_lvds = true;
 332                        break;
 333                case INTEL_OUTPUT_SDVO:
 334                        is_sdvo = true;
 335                        break;
 336                case INTEL_OUTPUT_MIPI:
 337                        is_mipi = true;
 338                        break;
 339                }
 340        }
 341
 342        /* Disable the VGA plane that we never use */
 343        REG_WRITE(VGACNTRL, VGA_DISP_DISABLE);
 344
 345        /* Disable the panel fitter if it was on our pipe */
 346        if (oaktrail_panel_fitter_pipe(dev) == pipe)
 347                REG_WRITE(PFIT_CONTROL, 0);
 348
 349        REG_WRITE(map->src,
 350                  ((mode->crtc_hdisplay - 1) << 16) |
 351                  (mode->crtc_vdisplay - 1));
 352
 353        if (psb_intel_encoder)
 354                drm_object_property_get_value(&connector->base,
 355                        dev->mode_config.scaling_mode_property, &scalingType);
 356
 357        if (scalingType == DRM_MODE_SCALE_NO_SCALE) {
 358                /* Moorestown doesn't have register support for centering so
 359                 * we need to mess with the h/vblank and h/vsync start and
 360                 * ends to get centering */
 361                int offsetX = 0, offsetY = 0;
 362
 363                offsetX = (adjusted_mode->crtc_hdisplay -
 364                           mode->crtc_hdisplay) / 2;
 365                offsetY = (adjusted_mode->crtc_vdisplay -
 366                           mode->crtc_vdisplay) / 2;
 367
 368                REG_WRITE(map->htotal, (mode->crtc_hdisplay - 1) |
 369                        ((adjusted_mode->crtc_htotal - 1) << 16));
 370                REG_WRITE(map->vtotal, (mode->crtc_vdisplay - 1) |
 371                        ((adjusted_mode->crtc_vtotal - 1) << 16));
 372                REG_WRITE(map->hblank,
 373                        (adjusted_mode->crtc_hblank_start - offsetX - 1) |
 374                        ((adjusted_mode->crtc_hblank_end - offsetX - 1) << 16));
 375                REG_WRITE(map->hsync,
 376                        (adjusted_mode->crtc_hsync_start - offsetX - 1) |
 377                        ((adjusted_mode->crtc_hsync_end - offsetX - 1) << 16));
 378                REG_WRITE(map->vblank,
 379                        (adjusted_mode->crtc_vblank_start - offsetY - 1) |
 380                        ((adjusted_mode->crtc_vblank_end - offsetY - 1) << 16));
 381                REG_WRITE(map->vsync,
 382                        (adjusted_mode->crtc_vsync_start - offsetY - 1) |
 383                        ((adjusted_mode->crtc_vsync_end - offsetY - 1) << 16));
 384        } else {
 385                REG_WRITE(map->htotal, (adjusted_mode->crtc_hdisplay - 1) |
 386                        ((adjusted_mode->crtc_htotal - 1) << 16));
 387                REG_WRITE(map->vtotal, (adjusted_mode->crtc_vdisplay - 1) |
 388                        ((adjusted_mode->crtc_vtotal - 1) << 16));
 389                REG_WRITE(map->hblank, (adjusted_mode->crtc_hblank_start - 1) |
 390                        ((adjusted_mode->crtc_hblank_end - 1) << 16));
 391                REG_WRITE(map->hsync, (adjusted_mode->crtc_hsync_start - 1) |
 392                        ((adjusted_mode->crtc_hsync_end - 1) << 16));
 393                REG_WRITE(map->vblank, (adjusted_mode->crtc_vblank_start - 1) |
 394                        ((adjusted_mode->crtc_vblank_end - 1) << 16));
 395                REG_WRITE(map->vsync, (adjusted_mode->crtc_vsync_start - 1) |
 396                        ((adjusted_mode->crtc_vsync_end - 1) << 16));
 397        }
 398
 399        /* Flush the plane changes */
 400        {
 401                struct drm_crtc_helper_funcs *crtc_funcs =
 402                    crtc->helper_private;
 403                crtc_funcs->mode_set_base(crtc, x, y, old_fb);
 404        }
 405
 406        /* setup pipeconf */
 407        pipeconf = REG_READ(map->conf);
 408
 409        /* Set up the display plane register */
 410        dspcntr = REG_READ(map->cntr);
 411        dspcntr |= DISPPLANE_GAMMA_ENABLE;
 412
 413        if (pipe == 0)
 414                dspcntr |= DISPPLANE_SEL_PIPE_A;
 415        else
 416                dspcntr |= DISPPLANE_SEL_PIPE_B;
 417
 418        if (is_mipi)
 419                goto oaktrail_crtc_mode_set_exit;
 420
 421        refclk = dev_priv->core_freq * 1000;
 422
 423        dpll = 0;               /*BIT16 = 0 for 100MHz reference */
 424
 425        ok = mrstFindBestPLL(crtc, adjusted_mode->clock, refclk, &clock);
 426
 427        if (!ok) {
 428                dev_dbg(dev->dev, "mrstFindBestPLL fail in oaktrail_crtc_mode_set.\n");
 429        } else {
 430                dev_dbg(dev->dev, "oaktrail_crtc_mode_set pixel clock = %d,"
 431                         "m = %x, p1 = %x.\n", clock.dot, clock.m,
 432                         clock.p1);
 433        }
 434
 435        fp = oaktrail_m_converts[(clock.m - MRST_M_MIN)] << 8;
 436
 437        dpll |= DPLL_VGA_MODE_DIS;
 438
 439
 440        dpll |= DPLL_VCO_ENABLE;
 441
 442        if (is_lvds)
 443                dpll |= DPLLA_MODE_LVDS;
 444        else
 445                dpll |= DPLLB_MODE_DAC_SERIAL;
 446
 447        if (is_sdvo) {
 448                int sdvo_pixel_multiply =
 449                    adjusted_mode->clock / mode->clock;
 450
 451                dpll |= DPLL_DVO_HIGH_SPEED;
 452                dpll |=
 453                    (sdvo_pixel_multiply -
 454                     1) << SDVO_MULTIPLIER_SHIFT_HIRES;
 455        }
 456
 457
 458        /* compute bitmask from p1 value */
 459        dpll |= (1 << (clock.p1 - 2)) << 17;
 460
 461        dpll |= DPLL_VCO_ENABLE;
 462
 463        mrstPrintPll("chosen", &clock);
 464
 465        if (dpll & DPLL_VCO_ENABLE) {
 466                REG_WRITE(map->fp0, fp);
 467                REG_WRITE(map->dpll, dpll & ~DPLL_VCO_ENABLE);
 468                REG_READ(map->dpll);
 469                /* Check the DPLLA lock bit PIPEACONF[29] */
 470                udelay(150);
 471        }
 472
 473        REG_WRITE(map->fp0, fp);
 474        REG_WRITE(map->dpll, dpll);
 475        REG_READ(map->dpll);
 476        /* Wait for the clocks to stabilize. */
 477        udelay(150);
 478
 479        /* write it again -- the BIOS does, after all */
 480        REG_WRITE(map->dpll, dpll);
 481        REG_READ(map->dpll);
 482        /* Wait for the clocks to stabilize. */
 483        udelay(150);
 484
 485        REG_WRITE(map->conf, pipeconf);
 486        REG_READ(map->conf);
 487        psb_intel_wait_for_vblank(dev);
 488
 489        REG_WRITE(map->cntr, dspcntr);
 490        psb_intel_wait_for_vblank(dev);
 491
 492oaktrail_crtc_mode_set_exit:
 493        gma_power_end(dev);
 494        return 0;
 495}
 496
 497static bool oaktrail_crtc_mode_fixup(struct drm_crtc *crtc,
 498                                  const struct drm_display_mode *mode,
 499                                  struct drm_display_mode *adjusted_mode)
 500{
 501        return true;
 502}
 503
 504static int oaktrail_pipe_set_base(struct drm_crtc *crtc,
 505                            int x, int y, struct drm_framebuffer *old_fb)
 506{
 507        struct drm_device *dev = crtc->dev;
 508        struct drm_psb_private *dev_priv = dev->dev_private;
 509        struct psb_intel_crtc *psb_intel_crtc = to_psb_intel_crtc(crtc);
 510        struct psb_framebuffer *psbfb = to_psb_fb(crtc->fb);
 511        int pipe = psb_intel_crtc->pipe;
 512        const struct psb_offset *map = &dev_priv->regmap[pipe];
 513        unsigned long start, offset;
 514
 515        u32 dspcntr;
 516        int ret = 0;
 517
 518        /* no fb bound */
 519        if (!crtc->fb) {
 520                dev_dbg(dev->dev, "No FB bound\n");
 521                return 0;
 522        }
 523
 524        if (!gma_power_begin(dev, true))
 525                return 0;
 526
 527        start = psbfb->gtt->offset;
 528        offset = y * crtc->fb->pitches[0] + x * (crtc->fb->bits_per_pixel / 8);
 529
 530        REG_WRITE(map->stride, crtc->fb->pitches[0]);
 531
 532        dspcntr = REG_READ(map->cntr);
 533        dspcntr &= ~DISPPLANE_PIXFORMAT_MASK;
 534
 535        switch (crtc->fb->bits_per_pixel) {
 536        case 8:
 537                dspcntr |= DISPPLANE_8BPP;
 538                break;
 539        case 16:
 540                if (crtc->fb->depth == 15)
 541                        dspcntr |= DISPPLANE_15_16BPP;
 542                else
 543                        dspcntr |= DISPPLANE_16BPP;
 544                break;
 545        case 24:
 546        case 32:
 547                dspcntr |= DISPPLANE_32BPP_NO_ALPHA;
 548                break;
 549        default:
 550                dev_err(dev->dev, "Unknown color depth\n");
 551                ret = -EINVAL;
 552                goto pipe_set_base_exit;
 553        }
 554        REG_WRITE(map->cntr, dspcntr);
 555
 556        REG_WRITE(map->base, offset);
 557        REG_READ(map->base);
 558        REG_WRITE(map->surf, start);
 559        REG_READ(map->surf);
 560
 561pipe_set_base_exit:
 562        gma_power_end(dev);
 563        return ret;
 564}
 565
 566static void oaktrail_crtc_prepare(struct drm_crtc *crtc)
 567{
 568        struct drm_crtc_helper_funcs *crtc_funcs = crtc->helper_private;
 569        crtc_funcs->dpms(crtc, DRM_MODE_DPMS_OFF);
 570}
 571
 572static void oaktrail_crtc_commit(struct drm_crtc *crtc)
 573{
 574        struct drm_crtc_helper_funcs *crtc_funcs = crtc->helper_private;
 575        crtc_funcs->dpms(crtc, DRM_MODE_DPMS_ON);
 576}
 577
 578const struct drm_crtc_helper_funcs oaktrail_helper_funcs = {
 579        .dpms = oaktrail_crtc_dpms,
 580        .mode_fixup = oaktrail_crtc_mode_fixup,
 581        .mode_set = oaktrail_crtc_mode_set,
 582        .mode_set_base = oaktrail_pipe_set_base,
 583        .prepare = oaktrail_crtc_prepare,
 584        .commit = oaktrail_crtc_commit,
 585};
 586
 587