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 29 struct psb_intel_range_t { 30 int min, max; 31 }; 32 33 struct oaktrail_limit_t { 34 struct psb_intel_range_t dot, m, p1; 35 }; 36 37 struct 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 60 static 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 79 static 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 85 static 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. */ 113 static void oaktrail_clock(int refclk, struct oaktrail_clock_t *clock) 114 { 115 clock->dot = (refclk * clock->m) / (14 * clock->p1); 116 } 117 118 static 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 */ 128 static bool 129 mrstFindBestPLL(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 */ 162 static void oaktrail_crtc_dpms(struct drm_crtc *crtc, int mode) 163 { 164 struct drm_device *dev = crtc->dev; 165 struct psb_intel_crtc *psb_intel_crtc = to_psb_intel_crtc(crtc); 166 int pipe = psb_intel_crtc->pipe; 167 int dpll_reg = (pipe == 0) ? MRST_DPLL_A : DPLL_B; 168 int dspcntr_reg = (pipe == 0) ? DSPACNTR : DSPBCNTR; 169 int dspbase_reg = (pipe == 0) ? MRST_DSPABASE : DSPBBASE; 170 int pipeconf_reg = (pipe == 0) ? PIPEACONF : PIPEBCONF; 171 u32 temp; 172 173 if (!gma_power_begin(dev, true)) 174 return; 175 176 /* XXX: When our outputs are all unaware of DPMS modes other than off 177 * and on, we should map those modes to DRM_MODE_DPMS_OFF in the CRTC. 178 */ 179 switch (mode) { 180 case DRM_MODE_DPMS_ON: 181 case DRM_MODE_DPMS_STANDBY: 182 case DRM_MODE_DPMS_SUSPEND: 183 /* Enable the DPLL */ 184 temp = REG_READ(dpll_reg); 185 if ((temp & DPLL_VCO_ENABLE) == 0) { 186 REG_WRITE(dpll_reg, temp); 187 REG_READ(dpll_reg); 188 /* Wait for the clocks to stabilize. */ 189 udelay(150); 190 REG_WRITE(dpll_reg, temp | DPLL_VCO_ENABLE); 191 REG_READ(dpll_reg); 192 /* Wait for the clocks to stabilize. */ 193 udelay(150); 194 REG_WRITE(dpll_reg, temp | DPLL_VCO_ENABLE); 195 REG_READ(dpll_reg); 196 /* Wait for the clocks to stabilize. */ 197 udelay(150); 198 } 199 /* Enable the pipe */ 200 temp = REG_READ(pipeconf_reg); 201 if ((temp & PIPEACONF_ENABLE) == 0) 202 REG_WRITE(pipeconf_reg, temp | PIPEACONF_ENABLE); 203 /* Enable the plane */ 204 temp = REG_READ(dspcntr_reg); 205 if ((temp & DISPLAY_PLANE_ENABLE) == 0) { 206 REG_WRITE(dspcntr_reg, 207 temp | DISPLAY_PLANE_ENABLE); 208 /* Flush the plane changes */ 209 REG_WRITE(dspbase_reg, REG_READ(dspbase_reg)); 210 } 211 212 psb_intel_crtc_load_lut(crtc); 213 214 /* Give the overlay scaler a chance to enable 215 if it's on this pipe */ 216 /* psb_intel_crtc_dpms_video(crtc, true); TODO */ 217 break; 218 case DRM_MODE_DPMS_OFF: 219 /* Give the overlay scaler a chance to disable 220 * if it's on this pipe */ 221 /* psb_intel_crtc_dpms_video(crtc, FALSE); TODO */ 222 223 /* Disable the VGA plane that we never use */ 224 REG_WRITE(VGACNTRL, VGA_DISP_DISABLE); 225 /* Disable display plane */ 226 temp = REG_READ(dspcntr_reg); 227 if ((temp & DISPLAY_PLANE_ENABLE) != 0) { 228 REG_WRITE(dspcntr_reg, 229 temp & ~DISPLAY_PLANE_ENABLE); 230 /* Flush the plane changes */ 231 REG_WRITE(dspbase_reg, REG_READ(dspbase_reg)); 232 REG_READ(dspbase_reg); 233 } 234 235 /* Next, disable display pipes */ 236 temp = REG_READ(pipeconf_reg); 237 if ((temp & PIPEACONF_ENABLE) != 0) { 238 REG_WRITE(pipeconf_reg, temp & ~PIPEACONF_ENABLE); 239 REG_READ(pipeconf_reg); 240 } 241 /* Wait for for the pipe disable to take effect. */ 242 psb_intel_wait_for_vblank(dev); 243 244 temp = REG_READ(dpll_reg); 245 if ((temp & DPLL_VCO_ENABLE) != 0) { 246 REG_WRITE(dpll_reg, temp & ~DPLL_VCO_ENABLE); 247 REG_READ(dpll_reg); 248 } 249 250 /* Wait for the clocks to turn off. */ 251 udelay(150); 252 break; 253 } 254 255 /*Set FIFO Watermarks*/ 256 REG_WRITE(DSPARB, 0x3FFF); 257 REG_WRITE(DSPFW1, 0x3F88080A); 258 REG_WRITE(DSPFW2, 0x0b060808); 259 REG_WRITE(DSPFW3, 0x0); 260 REG_WRITE(DSPFW4, 0x08030404); 261 REG_WRITE(DSPFW5, 0x04040404); 262 REG_WRITE(DSPFW6, 0x78); 263 REG_WRITE(0x70400, REG_READ(0x70400) | 0x4000); 264 /* Must write Bit 14 of the Chicken Bit Register */ 265 266 gma_power_end(dev); 267 } 268 269 /** 270 * Return the pipe currently connected to the panel fitter, 271 * or -1 if the panel fitter is not present or not in use 272 */ 273 static int oaktrail_panel_fitter_pipe(struct drm_device *dev) 274 { 275 u32 pfit_control; 276 277 pfit_control = REG_READ(PFIT_CONTROL); 278 279 /* See if the panel fitter is in use */ 280 if ((pfit_control & PFIT_ENABLE) == 0) 281 return -1; 282 return (pfit_control >> 29) & 3; 283 } 284 285 static int oaktrail_crtc_mode_set(struct drm_crtc *crtc, 286 struct drm_display_mode *mode, 287 struct drm_display_mode *adjusted_mode, 288 int x, int y, 289 struct drm_framebuffer *old_fb) 290 { 291 struct drm_device *dev = crtc->dev; 292 struct psb_intel_crtc *psb_intel_crtc = to_psb_intel_crtc(crtc); 293 struct drm_psb_private *dev_priv = dev->dev_private; 294 int pipe = psb_intel_crtc->pipe; 295 int fp_reg = (pipe == 0) ? MRST_FPA0 : FPB0; 296 int dpll_reg = (pipe == 0) ? MRST_DPLL_A : DPLL_B; 297 int dspcntr_reg = (pipe == 0) ? DSPACNTR : DSPBCNTR; 298 int pipeconf_reg = (pipe == 0) ? PIPEACONF : PIPEBCONF; 299 int htot_reg = (pipe == 0) ? HTOTAL_A : HTOTAL_B; 300 int hblank_reg = (pipe == 0) ? HBLANK_A : HBLANK_B; 301 int hsync_reg = (pipe == 0) ? HSYNC_A : HSYNC_B; 302 int vtot_reg = (pipe == 0) ? VTOTAL_A : VTOTAL_B; 303 int vblank_reg = (pipe == 0) ? VBLANK_A : VBLANK_B; 304 int vsync_reg = (pipe == 0) ? VSYNC_A : VSYNC_B; 305 int pipesrc_reg = (pipe == 0) ? PIPEASRC : PIPEBSRC; 306 int refclk = 0; 307 struct oaktrail_clock_t clock; 308 u32 dpll = 0, fp = 0, dspcntr, pipeconf; 309 bool ok, is_sdvo = false; 310 bool is_lvds = false; 311 bool is_mipi = false; 312 struct drm_mode_config *mode_config = &dev->mode_config; 313 struct psb_intel_encoder *psb_intel_encoder = NULL; 314 uint64_t scalingType = DRM_MODE_SCALE_FULLSCREEN; 315 struct drm_connector *connector; 316 317 if (!gma_power_begin(dev, true)) 318 return 0; 319 320 memcpy(&psb_intel_crtc->saved_mode, 321 mode, 322 sizeof(struct drm_display_mode)); 323 memcpy(&psb_intel_crtc->saved_adjusted_mode, 324 adjusted_mode, 325 sizeof(struct drm_display_mode)); 326 327 list_for_each_entry(connector, &mode_config->connector_list, head) { 328 if (!connector->encoder || connector->encoder->crtc != crtc) 329 continue; 330 331 psb_intel_encoder = psb_intel_attached_encoder(connector); 332 333 switch (psb_intel_encoder->type) { 334 case INTEL_OUTPUT_LVDS: 335 is_lvds = true; 336 break; 337 case INTEL_OUTPUT_SDVO: 338 is_sdvo = true; 339 break; 340 case INTEL_OUTPUT_MIPI: 341 is_mipi = true; 342 break; 343 } 344 } 345 346 /* Disable the VGA plane that we never use */ 347 REG_WRITE(VGACNTRL, VGA_DISP_DISABLE); 348 349 /* Disable the panel fitter if it was on our pipe */ 350 if (oaktrail_panel_fitter_pipe(dev) == pipe) 351 REG_WRITE(PFIT_CONTROL, 0); 352 353 REG_WRITE(pipesrc_reg, 354 ((mode->crtc_hdisplay - 1) << 16) | 355 (mode->crtc_vdisplay - 1)); 356 357 if (psb_intel_encoder) 358 drm_connector_property_get_value(connector, 359 dev->mode_config.scaling_mode_property, &scalingType); 360 361 if (scalingType == DRM_MODE_SCALE_NO_SCALE) { 362 /* Moorestown doesn't have register support for centering so 363 * we need to mess with the h/vblank and h/vsync start and 364 * ends to get centering */ 365 int offsetX = 0, offsetY = 0; 366 367 offsetX = (adjusted_mode->crtc_hdisplay - 368 mode->crtc_hdisplay) / 2; 369 offsetY = (adjusted_mode->crtc_vdisplay - 370 mode->crtc_vdisplay) / 2; 371 372 REG_WRITE(htot_reg, (mode->crtc_hdisplay - 1) | 373 ((adjusted_mode->crtc_htotal - 1) << 16)); 374 REG_WRITE(vtot_reg, (mode->crtc_vdisplay - 1) | 375 ((adjusted_mode->crtc_vtotal - 1) << 16)); 376 REG_WRITE(hblank_reg, 377 (adjusted_mode->crtc_hblank_start - offsetX - 1) | 378 ((adjusted_mode->crtc_hblank_end - offsetX - 1) << 16)); 379 REG_WRITE(hsync_reg, 380 (adjusted_mode->crtc_hsync_start - offsetX - 1) | 381 ((adjusted_mode->crtc_hsync_end - offsetX - 1) << 16)); 382 REG_WRITE(vblank_reg, 383 (adjusted_mode->crtc_vblank_start - offsetY - 1) | 384 ((adjusted_mode->crtc_vblank_end - offsetY - 1) << 16)); 385 REG_WRITE(vsync_reg, 386 (adjusted_mode->crtc_vsync_start - offsetY - 1) | 387 ((adjusted_mode->crtc_vsync_end - offsetY - 1) << 16)); 388 } else { 389 REG_WRITE(htot_reg, (adjusted_mode->crtc_hdisplay - 1) | 390 ((adjusted_mode->crtc_htotal - 1) << 16)); 391 REG_WRITE(vtot_reg, (adjusted_mode->crtc_vdisplay - 1) | 392 ((adjusted_mode->crtc_vtotal - 1) << 16)); 393 REG_WRITE(hblank_reg, (adjusted_mode->crtc_hblank_start - 1) | 394 ((adjusted_mode->crtc_hblank_end - 1) << 16)); 395 REG_WRITE(hsync_reg, (adjusted_mode->crtc_hsync_start - 1) | 396 ((adjusted_mode->crtc_hsync_end - 1) << 16)); 397 REG_WRITE(vblank_reg, (adjusted_mode->crtc_vblank_start - 1) | 398 ((adjusted_mode->crtc_vblank_end - 1) << 16)); 399 REG_WRITE(vsync_reg, (adjusted_mode->crtc_vsync_start - 1) | 400 ((adjusted_mode->crtc_vsync_end - 1) << 16)); 401 } 402 403 /* Flush the plane changes */ 404 { 405 struct drm_crtc_helper_funcs *crtc_funcs = 406 crtc->helper_private; 407 crtc_funcs->mode_set_base(crtc, x, y, old_fb); 408 } 409 410 /* setup pipeconf */ 411 pipeconf = REG_READ(pipeconf_reg); 412 413 /* Set up the display plane register */ 414 dspcntr = REG_READ(dspcntr_reg); 415 dspcntr |= DISPPLANE_GAMMA_ENABLE; 416 417 if (pipe == 0) 418 dspcntr |= DISPPLANE_SEL_PIPE_A; 419 else 420 dspcntr |= DISPPLANE_SEL_PIPE_B; 421 422 if (is_mipi) 423 goto oaktrail_crtc_mode_set_exit; 424 425 refclk = dev_priv->core_freq * 1000; 426 427 dpll = 0; /*BIT16 = 0 for 100MHz reference */ 428 429 ok = mrstFindBestPLL(crtc, adjusted_mode->clock, refclk, &clock); 430 431 if (!ok) { 432 dev_dbg(dev->dev, "mrstFindBestPLL fail in oaktrail_crtc_mode_set.\n"); 433 } else { 434 dev_dbg(dev->dev, "oaktrail_crtc_mode_set pixel clock = %d," 435 "m = %x, p1 = %x.\n", clock.dot, clock.m, 436 clock.p1); 437 } 438 439 fp = oaktrail_m_converts[(clock.m - MRST_M_MIN)] << 8; 440 441 dpll |= DPLL_VGA_MODE_DIS; 442 443 444 dpll |= DPLL_VCO_ENABLE; 445 446 if (is_lvds) 447 dpll |= DPLLA_MODE_LVDS; 448 else 449 dpll |= DPLLB_MODE_DAC_SERIAL; 450 451 if (is_sdvo) { 452 int sdvo_pixel_multiply = 453 adjusted_mode->clock / mode->clock; 454 455 dpll |= DPLL_DVO_HIGH_SPEED; 456 dpll |= 457 (sdvo_pixel_multiply - 458 1) << SDVO_MULTIPLIER_SHIFT_HIRES; 459 } 460 461 462 /* compute bitmask from p1 value */ 463 dpll |= (1 << (clock.p1 - 2)) << 17; 464 465 dpll |= DPLL_VCO_ENABLE; 466 467 mrstPrintPll("chosen", &clock); 468 469 if (dpll & DPLL_VCO_ENABLE) { 470 REG_WRITE(fp_reg, fp); 471 REG_WRITE(dpll_reg, dpll & ~DPLL_VCO_ENABLE); 472 REG_READ(dpll_reg); 473 /* Check the DPLLA lock bit PIPEACONF[29] */ 474 udelay(150); 475 } 476 477 REG_WRITE(fp_reg, fp); 478 REG_WRITE(dpll_reg, dpll); 479 REG_READ(dpll_reg); 480 /* Wait for the clocks to stabilize. */ 481 udelay(150); 482 483 /* write it again -- the BIOS does, after all */ 484 REG_WRITE(dpll_reg, dpll); 485 REG_READ(dpll_reg); 486 /* Wait for the clocks to stabilize. */ 487 udelay(150); 488 489 REG_WRITE(pipeconf_reg, pipeconf); 490 REG_READ(pipeconf_reg); 491 psb_intel_wait_for_vblank(dev); 492 493 REG_WRITE(dspcntr_reg, dspcntr); 494 psb_intel_wait_for_vblank(dev); 495 496 oaktrail_crtc_mode_set_exit: 497 gma_power_end(dev); 498 return 0; 499 } 500 501 static bool oaktrail_crtc_mode_fixup(struct drm_crtc *crtc, 502 struct drm_display_mode *mode, 503 struct drm_display_mode *adjusted_mode) 504 { 505 return true; 506 } 507 508 static int oaktrail_pipe_set_base(struct drm_crtc *crtc, 509 int x, int y, struct drm_framebuffer *old_fb) 510 { 511 struct drm_device *dev = crtc->dev; 512 struct psb_intel_crtc *psb_intel_crtc = to_psb_intel_crtc(crtc); 513 struct psb_framebuffer *psbfb = to_psb_fb(crtc->fb); 514 int pipe = psb_intel_crtc->pipe; 515 unsigned long start, offset; 516 517 int dspbase = (pipe == 0 ? DSPALINOFF : DSPBBASE); 518 int dspsurf = (pipe == 0 ? DSPASURF : DSPBSURF); 519 int dspstride = (pipe == 0) ? DSPASTRIDE : DSPBSTRIDE; 520 int dspcntr_reg = (pipe == 0) ? DSPACNTR : DSPBCNTR; 521 u32 dspcntr; 522 int ret = 0; 523 524 /* no fb bound */ 525 if (!crtc->fb) { 526 dev_dbg(dev->dev, "No FB bound\n"); 527 return 0; 528 } 529 530 if (!gma_power_begin(dev, true)) 531 return 0; 532 533 start = psbfb->gtt->offset; 534 offset = y * crtc->fb->pitches[0] + x * (crtc->fb->bits_per_pixel / 8); 535 536 REG_WRITE(dspstride, crtc->fb->pitches[0]); 537 538 dspcntr = REG_READ(dspcntr_reg); 539 dspcntr &= ~DISPPLANE_PIXFORMAT_MASK; 540 541 switch (crtc->fb->bits_per_pixel) { 542 case 8: 543 dspcntr |= DISPPLANE_8BPP; 544 break; 545 case 16: 546 if (crtc->fb->depth == 15) 547 dspcntr |= DISPPLANE_15_16BPP; 548 else 549 dspcntr |= DISPPLANE_16BPP; 550 break; 551 case 24: 552 case 32: 553 dspcntr |= DISPPLANE_32BPP_NO_ALPHA; 554 break; 555 default: 556 dev_err(dev->dev, "Unknown color depth\n"); 557 ret = -EINVAL; 558 goto pipe_set_base_exit; 559 } 560 REG_WRITE(dspcntr_reg, dspcntr); 561 562 REG_WRITE(dspbase, offset); 563 REG_READ(dspbase); 564 REG_WRITE(dspsurf, start); 565 REG_READ(dspsurf); 566 567 pipe_set_base_exit: 568 gma_power_end(dev); 569 return ret; 570 } 571 572 static void oaktrail_crtc_prepare(struct drm_crtc *crtc) 573 { 574 struct drm_crtc_helper_funcs *crtc_funcs = crtc->helper_private; 575 crtc_funcs->dpms(crtc, DRM_MODE_DPMS_OFF); 576 } 577 578 static void oaktrail_crtc_commit(struct drm_crtc *crtc) 579 { 580 struct drm_crtc_helper_funcs *crtc_funcs = crtc->helper_private; 581 crtc_funcs->dpms(crtc, DRM_MODE_DPMS_ON); 582 } 583 584 const struct drm_crtc_helper_funcs oaktrail_helper_funcs = { 585 .dpms = oaktrail_crtc_dpms, 586 .mode_fixup = oaktrail_crtc_mode_fixup, 587 .mode_set = oaktrail_crtc_mode_set, 588 .mode_set_base = oaktrail_pipe_set_base, 589 .prepare = oaktrail_crtc_prepare, 590 .commit = oaktrail_crtc_commit, 591 }; 592 593