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