linux/drivers/gpu/drm/gma500/oaktrail_device.c
<<
>>
Prefs
   1/**************************************************************************
   2 * Copyright (c) 2011, Intel Corporation.
   3 * All Rights Reserved.
   4 *
   5 * This program is free software; you can redistribute it and/or modify it
   6 * under the terms and conditions of the GNU General Public License,
   7 * version 2, as published by the Free Software Foundation.
   8 *
   9 * This program is distributed in the hope it will be useful, but WITHOUT
  10 * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
  11 * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License for
  12 * more details.
  13 *
  14 * You should have received a copy of the GNU General Public License along with
  15 * this program; if not, write to the Free Software Foundation, Inc.,
  16 * 51 Franklin St - Fifth Floor, Boston, MA 02110-1301 USA.
  17 *
  18 **************************************************************************/
  19
  20#include <linux/backlight.h>
  21#include <linux/module.h>
  22#include <linux/dmi.h>
  23#include <drm/drmP.h>
  24#include <drm/drm.h>
  25#include <drm/gma_drm.h>
  26#include "psb_drv.h"
  27#include "psb_reg.h"
  28#include "psb_intel_reg.h"
  29#include <asm/intel-mid.h>
  30#include <asm/intel_scu_ipc.h>
  31#include "mid_bios.h"
  32#include "intel_bios.h"
  33
  34static int oaktrail_output_init(struct drm_device *dev)
  35{
  36        struct drm_psb_private *dev_priv = dev->dev_private;
  37        if (dev_priv->iLVDS_enable)
  38                oaktrail_lvds_init(dev, &dev_priv->mode_dev);
  39        else
  40                dev_err(dev->dev, "DSI is not supported\n");
  41        if (dev_priv->hdmi_priv)
  42                oaktrail_hdmi_init(dev, &dev_priv->mode_dev);
  43
  44        psb_intel_sdvo_init(dev, SDVOB);
  45
  46        return 0;
  47}
  48
  49/*
  50 *      Provide the low level interfaces for the Moorestown backlight
  51 */
  52
  53#ifdef CONFIG_BACKLIGHT_CLASS_DEVICE
  54
  55#define MRST_BLC_MAX_PWM_REG_FREQ           0xFFFF
  56#define BLC_PWM_PRECISION_FACTOR 100    /* 10000000 */
  57#define BLC_PWM_FREQ_CALC_CONSTANT 32
  58#define MHz 1000000
  59#define BLC_ADJUSTMENT_MAX 100
  60
  61static struct backlight_device *oaktrail_backlight_device;
  62static int oaktrail_brightness;
  63
  64static int oaktrail_set_brightness(struct backlight_device *bd)
  65{
  66        struct drm_device *dev = bl_get_data(oaktrail_backlight_device);
  67        struct drm_psb_private *dev_priv = dev->dev_private;
  68        int level = bd->props.brightness;
  69        u32 blc_pwm_ctl;
  70        u32 max_pwm_blc;
  71
  72        /* Percentage 1-100% being valid */
  73        if (level < 1)
  74                level = 1;
  75
  76        if (gma_power_begin(dev, 0)) {
  77                /* Calculate and set the brightness value */
  78                max_pwm_blc = REG_READ(BLC_PWM_CTL) >> 16;
  79                blc_pwm_ctl = level * max_pwm_blc / 100;
  80
  81                /* Adjust the backlight level with the percent in
  82                 * dev_priv->blc_adj1;
  83                 */
  84                blc_pwm_ctl = blc_pwm_ctl * dev_priv->blc_adj1;
  85                blc_pwm_ctl = blc_pwm_ctl / 100;
  86
  87                /* Adjust the backlight level with the percent in
  88                 * dev_priv->blc_adj2;
  89                 */
  90                blc_pwm_ctl = blc_pwm_ctl * dev_priv->blc_adj2;
  91                blc_pwm_ctl = blc_pwm_ctl / 100;
  92
  93                /* force PWM bit on */
  94                REG_WRITE(BLC_PWM_CTL2, (0x80000000 | REG_READ(BLC_PWM_CTL2)));
  95                REG_WRITE(BLC_PWM_CTL, (max_pwm_blc << 16) | blc_pwm_ctl);
  96                gma_power_end(dev);
  97        }
  98        oaktrail_brightness = level;
  99        return 0;
 100}
 101
 102static int oaktrail_get_brightness(struct backlight_device *bd)
 103{
 104        /* return locally cached var instead of HW read (due to DPST etc.) */
 105        /* FIXME: ideally return actual value in case firmware fiddled with
 106           it */
 107        return oaktrail_brightness;
 108}
 109
 110static int device_backlight_init(struct drm_device *dev)
 111{
 112        struct drm_psb_private *dev_priv = dev->dev_private;
 113        unsigned long core_clock;
 114        u16 bl_max_freq;
 115        uint32_t value;
 116        uint32_t blc_pwm_precision_factor;
 117
 118        dev_priv->blc_adj1 = BLC_ADJUSTMENT_MAX;
 119        dev_priv->blc_adj2 = BLC_ADJUSTMENT_MAX;
 120        bl_max_freq = 256;
 121        /* this needs to be set elsewhere */
 122        blc_pwm_precision_factor = BLC_PWM_PRECISION_FACTOR;
 123
 124        core_clock = dev_priv->core_freq;
 125
 126        value = (core_clock * MHz) / BLC_PWM_FREQ_CALC_CONSTANT;
 127        value *= blc_pwm_precision_factor;
 128        value /= bl_max_freq;
 129        value /= blc_pwm_precision_factor;
 130
 131        if (value > (unsigned long long)MRST_BLC_MAX_PWM_REG_FREQ)
 132                        return -ERANGE;
 133
 134        if (gma_power_begin(dev, false)) {
 135                REG_WRITE(BLC_PWM_CTL2, (0x80000000 | REG_READ(BLC_PWM_CTL2)));
 136                REG_WRITE(BLC_PWM_CTL, value | (value << 16));
 137                gma_power_end(dev);
 138        }
 139        return 0;
 140}
 141
 142static const struct backlight_ops oaktrail_ops = {
 143        .get_brightness = oaktrail_get_brightness,
 144        .update_status  = oaktrail_set_brightness,
 145};
 146
 147static int oaktrail_backlight_init(struct drm_device *dev)
 148{
 149        struct drm_psb_private *dev_priv = dev->dev_private;
 150        int ret;
 151        struct backlight_properties props;
 152
 153        memset(&props, 0, sizeof(struct backlight_properties));
 154        props.max_brightness = 100;
 155        props.type = BACKLIGHT_PLATFORM;
 156
 157        oaktrail_backlight_device = backlight_device_register("oaktrail-bl",
 158                                NULL, (void *)dev, &oaktrail_ops, &props);
 159
 160        if (IS_ERR(oaktrail_backlight_device))
 161                return PTR_ERR(oaktrail_backlight_device);
 162
 163        ret = device_backlight_init(dev);
 164        if (ret < 0) {
 165                backlight_device_unregister(oaktrail_backlight_device);
 166                return ret;
 167        }
 168        oaktrail_backlight_device->props.brightness = 100;
 169        oaktrail_backlight_device->props.max_brightness = 100;
 170        backlight_update_status(oaktrail_backlight_device);
 171        dev_priv->backlight_device = oaktrail_backlight_device;
 172        return 0;
 173}
 174
 175#endif
 176
 177/*
 178 *      Provide the Moorestown specific chip logic and low level methods
 179 *      for power management
 180 */
 181
 182/**
 183 *      oaktrail_save_display_registers -       save registers lost on suspend
 184 *      @dev: our DRM device
 185 *
 186 *      Save the state we need in order to be able to restore the interface
 187 *      upon resume from suspend
 188 */
 189static int oaktrail_save_display_registers(struct drm_device *dev)
 190{
 191        struct drm_psb_private *dev_priv = dev->dev_private;
 192        struct psb_save_area *regs = &dev_priv->regs;
 193        struct psb_pipe *p = &regs->pipe[0];
 194        int i;
 195        u32 pp_stat;
 196
 197        /* Display arbitration control + watermarks */
 198        regs->psb.saveDSPARB = PSB_RVDC32(DSPARB);
 199        regs->psb.saveDSPFW1 = PSB_RVDC32(DSPFW1);
 200        regs->psb.saveDSPFW2 = PSB_RVDC32(DSPFW2);
 201        regs->psb.saveDSPFW3 = PSB_RVDC32(DSPFW3);
 202        regs->psb.saveDSPFW4 = PSB_RVDC32(DSPFW4);
 203        regs->psb.saveDSPFW5 = PSB_RVDC32(DSPFW5);
 204        regs->psb.saveDSPFW6 = PSB_RVDC32(DSPFW6);
 205        regs->psb.saveCHICKENBIT = PSB_RVDC32(DSPCHICKENBIT);
 206
 207        /* Pipe & plane A info */
 208        p->conf = PSB_RVDC32(PIPEACONF);
 209        p->src = PSB_RVDC32(PIPEASRC);
 210        p->fp0 = PSB_RVDC32(MRST_FPA0);
 211        p->fp1 = PSB_RVDC32(MRST_FPA1);
 212        p->dpll = PSB_RVDC32(MRST_DPLL_A);
 213        p->htotal = PSB_RVDC32(HTOTAL_A);
 214        p->hblank = PSB_RVDC32(HBLANK_A);
 215        p->hsync = PSB_RVDC32(HSYNC_A);
 216        p->vtotal = PSB_RVDC32(VTOTAL_A);
 217        p->vblank = PSB_RVDC32(VBLANK_A);
 218        p->vsync = PSB_RVDC32(VSYNC_A);
 219        regs->psb.saveBCLRPAT_A = PSB_RVDC32(BCLRPAT_A);
 220        p->cntr = PSB_RVDC32(DSPACNTR);
 221        p->stride = PSB_RVDC32(DSPASTRIDE);
 222        p->addr = PSB_RVDC32(DSPABASE);
 223        p->surf = PSB_RVDC32(DSPASURF);
 224        p->linoff = PSB_RVDC32(DSPALINOFF);
 225        p->tileoff = PSB_RVDC32(DSPATILEOFF);
 226
 227        /* Save cursor regs */
 228        regs->psb.saveDSPACURSOR_CTRL = PSB_RVDC32(CURACNTR);
 229        regs->psb.saveDSPACURSOR_BASE = PSB_RVDC32(CURABASE);
 230        regs->psb.saveDSPACURSOR_POS = PSB_RVDC32(CURAPOS);
 231
 232        /* Save palette (gamma) */
 233        for (i = 0; i < 256; i++)
 234                p->palette[i] = PSB_RVDC32(PALETTE_A + (i << 2));
 235
 236        if (dev_priv->hdmi_priv)
 237                oaktrail_hdmi_save(dev);
 238
 239        /* Save performance state */
 240        regs->psb.savePERF_MODE = PSB_RVDC32(MRST_PERF_MODE);
 241
 242        /* LVDS state */
 243        regs->psb.savePP_CONTROL = PSB_RVDC32(PP_CONTROL);
 244        regs->psb.savePFIT_PGM_RATIOS = PSB_RVDC32(PFIT_PGM_RATIOS);
 245        regs->psb.savePFIT_AUTO_RATIOS = PSB_RVDC32(PFIT_AUTO_RATIOS);
 246        regs->saveBLC_PWM_CTL = PSB_RVDC32(BLC_PWM_CTL);
 247        regs->saveBLC_PWM_CTL2 = PSB_RVDC32(BLC_PWM_CTL2);
 248        regs->psb.saveLVDS = PSB_RVDC32(LVDS);
 249        regs->psb.savePFIT_CONTROL = PSB_RVDC32(PFIT_CONTROL);
 250        regs->psb.savePP_ON_DELAYS = PSB_RVDC32(LVDSPP_ON);
 251        regs->psb.savePP_OFF_DELAYS = PSB_RVDC32(LVDSPP_OFF);
 252        regs->psb.savePP_DIVISOR = PSB_RVDC32(PP_CYCLE);
 253
 254        /* HW overlay */
 255        regs->psb.saveOV_OVADD = PSB_RVDC32(OV_OVADD);
 256        regs->psb.saveOV_OGAMC0 = PSB_RVDC32(OV_OGAMC0);
 257        regs->psb.saveOV_OGAMC1 = PSB_RVDC32(OV_OGAMC1);
 258        regs->psb.saveOV_OGAMC2 = PSB_RVDC32(OV_OGAMC2);
 259        regs->psb.saveOV_OGAMC3 = PSB_RVDC32(OV_OGAMC3);
 260        regs->psb.saveOV_OGAMC4 = PSB_RVDC32(OV_OGAMC4);
 261        regs->psb.saveOV_OGAMC5 = PSB_RVDC32(OV_OGAMC5);
 262
 263        /* DPST registers */
 264        regs->psb.saveHISTOGRAM_INT_CONTROL_REG =
 265                                        PSB_RVDC32(HISTOGRAM_INT_CONTROL);
 266        regs->psb.saveHISTOGRAM_LOGIC_CONTROL_REG =
 267                                        PSB_RVDC32(HISTOGRAM_LOGIC_CONTROL);
 268        regs->psb.savePWM_CONTROL_LOGIC = PSB_RVDC32(PWM_CONTROL_LOGIC);
 269
 270        if (dev_priv->iLVDS_enable) {
 271                /* Shut down the panel */
 272                PSB_WVDC32(0, PP_CONTROL);
 273
 274                do {
 275                        pp_stat = PSB_RVDC32(PP_STATUS);
 276                } while (pp_stat & 0x80000000);
 277
 278                /* Turn off the plane */
 279                PSB_WVDC32(0x58000000, DSPACNTR);
 280                /* Trigger the plane disable */
 281                PSB_WVDC32(0, DSPASURF);
 282
 283                /* Wait ~4 ticks */
 284                msleep(4);
 285
 286                /* Turn off pipe */
 287                PSB_WVDC32(0x0, PIPEACONF);
 288                /* Wait ~8 ticks */
 289                msleep(8);
 290
 291                /* Turn off PLLs */
 292                PSB_WVDC32(0, MRST_DPLL_A);
 293        }
 294        return 0;
 295}
 296
 297/**
 298 *      oaktrail_restore_display_registers      -       restore lost register state
 299 *      @dev: our DRM device
 300 *
 301 *      Restore register state that was lost during suspend and resume.
 302 */
 303static int oaktrail_restore_display_registers(struct drm_device *dev)
 304{
 305        struct drm_psb_private *dev_priv = dev->dev_private;
 306        struct psb_save_area *regs = &dev_priv->regs;
 307        struct psb_pipe *p = &regs->pipe[0];
 308        u32 pp_stat;
 309        int i;
 310
 311        /* Display arbitration + watermarks */
 312        PSB_WVDC32(regs->psb.saveDSPARB, DSPARB);
 313        PSB_WVDC32(regs->psb.saveDSPFW1, DSPFW1);
 314        PSB_WVDC32(regs->psb.saveDSPFW2, DSPFW2);
 315        PSB_WVDC32(regs->psb.saveDSPFW3, DSPFW3);
 316        PSB_WVDC32(regs->psb.saveDSPFW4, DSPFW4);
 317        PSB_WVDC32(regs->psb.saveDSPFW5, DSPFW5);
 318        PSB_WVDC32(regs->psb.saveDSPFW6, DSPFW6);
 319        PSB_WVDC32(regs->psb.saveCHICKENBIT, DSPCHICKENBIT);
 320
 321        /* Make sure VGA plane is off. it initializes to on after reset!*/
 322        PSB_WVDC32(0x80000000, VGACNTRL);
 323
 324        /* set the plls */
 325        PSB_WVDC32(p->fp0, MRST_FPA0);
 326        PSB_WVDC32(p->fp1, MRST_FPA1);
 327
 328        /* Actually enable it */
 329        PSB_WVDC32(p->dpll, MRST_DPLL_A);
 330        DRM_UDELAY(150);
 331
 332        /* Restore mode */
 333        PSB_WVDC32(p->htotal, HTOTAL_A);
 334        PSB_WVDC32(p->hblank, HBLANK_A);
 335        PSB_WVDC32(p->hsync, HSYNC_A);
 336        PSB_WVDC32(p->vtotal, VTOTAL_A);
 337        PSB_WVDC32(p->vblank, VBLANK_A);
 338        PSB_WVDC32(p->vsync, VSYNC_A);
 339        PSB_WVDC32(p->src, PIPEASRC);
 340        PSB_WVDC32(regs->psb.saveBCLRPAT_A, BCLRPAT_A);
 341
 342        /* Restore performance mode*/
 343        PSB_WVDC32(regs->psb.savePERF_MODE, MRST_PERF_MODE);
 344
 345        /* Enable the pipe*/
 346        if (dev_priv->iLVDS_enable)
 347                PSB_WVDC32(p->conf, PIPEACONF);
 348
 349        /* Set up the plane*/
 350        PSB_WVDC32(p->linoff, DSPALINOFF);
 351        PSB_WVDC32(p->stride, DSPASTRIDE);
 352        PSB_WVDC32(p->tileoff, DSPATILEOFF);
 353
 354        /* Enable the plane */
 355        PSB_WVDC32(p->cntr, DSPACNTR);
 356        PSB_WVDC32(p->surf, DSPASURF);
 357
 358        /* Enable Cursor A */
 359        PSB_WVDC32(regs->psb.saveDSPACURSOR_CTRL, CURACNTR);
 360        PSB_WVDC32(regs->psb.saveDSPACURSOR_POS, CURAPOS);
 361        PSB_WVDC32(regs->psb.saveDSPACURSOR_BASE, CURABASE);
 362
 363        /* Restore palette (gamma) */
 364        for (i = 0; i < 256; i++)
 365                PSB_WVDC32(p->palette[i], PALETTE_A + (i << 2));
 366
 367        if (dev_priv->hdmi_priv)
 368                oaktrail_hdmi_restore(dev);
 369
 370        if (dev_priv->iLVDS_enable) {
 371                PSB_WVDC32(regs->saveBLC_PWM_CTL2, BLC_PWM_CTL2);
 372                PSB_WVDC32(regs->psb.saveLVDS, LVDS); /*port 61180h*/
 373                PSB_WVDC32(regs->psb.savePFIT_CONTROL, PFIT_CONTROL);
 374                PSB_WVDC32(regs->psb.savePFIT_PGM_RATIOS, PFIT_PGM_RATIOS);
 375                PSB_WVDC32(regs->psb.savePFIT_AUTO_RATIOS, PFIT_AUTO_RATIOS);
 376                PSB_WVDC32(regs->saveBLC_PWM_CTL, BLC_PWM_CTL);
 377                PSB_WVDC32(regs->psb.savePP_ON_DELAYS, LVDSPP_ON);
 378                PSB_WVDC32(regs->psb.savePP_OFF_DELAYS, LVDSPP_OFF);
 379                PSB_WVDC32(regs->psb.savePP_DIVISOR, PP_CYCLE);
 380                PSB_WVDC32(regs->psb.savePP_CONTROL, PP_CONTROL);
 381        }
 382
 383        /* Wait for cycle delay */
 384        do {
 385                pp_stat = PSB_RVDC32(PP_STATUS);
 386        } while (pp_stat & 0x08000000);
 387
 388        /* Wait for panel power up */
 389        do {
 390                pp_stat = PSB_RVDC32(PP_STATUS);
 391        } while (pp_stat & 0x10000000);
 392
 393        /* Restore HW overlay */
 394        PSB_WVDC32(regs->psb.saveOV_OVADD, OV_OVADD);
 395        PSB_WVDC32(regs->psb.saveOV_OGAMC0, OV_OGAMC0);
 396        PSB_WVDC32(regs->psb.saveOV_OGAMC1, OV_OGAMC1);
 397        PSB_WVDC32(regs->psb.saveOV_OGAMC2, OV_OGAMC2);
 398        PSB_WVDC32(regs->psb.saveOV_OGAMC3, OV_OGAMC3);
 399        PSB_WVDC32(regs->psb.saveOV_OGAMC4, OV_OGAMC4);
 400        PSB_WVDC32(regs->psb.saveOV_OGAMC5, OV_OGAMC5);
 401
 402        /* DPST registers */
 403        PSB_WVDC32(regs->psb.saveHISTOGRAM_INT_CONTROL_REG,
 404                                                HISTOGRAM_INT_CONTROL);
 405        PSB_WVDC32(regs->psb.saveHISTOGRAM_LOGIC_CONTROL_REG,
 406                                                HISTOGRAM_LOGIC_CONTROL);
 407        PSB_WVDC32(regs->psb.savePWM_CONTROL_LOGIC, PWM_CONTROL_LOGIC);
 408
 409        return 0;
 410}
 411
 412/**
 413 *      oaktrail_power_down     -       power down the display island
 414 *      @dev: our DRM device
 415 *
 416 *      Power down the display interface of our device
 417 */
 418static int oaktrail_power_down(struct drm_device *dev)
 419{
 420        struct drm_psb_private *dev_priv = dev->dev_private;
 421        u32 pwr_mask ;
 422        u32 pwr_sts;
 423
 424        pwr_mask = PSB_PWRGT_DISPLAY_MASK;
 425        outl(pwr_mask, dev_priv->ospm_base + PSB_PM_SSC);
 426
 427        while (true) {
 428                pwr_sts = inl(dev_priv->ospm_base + PSB_PM_SSS);
 429                if ((pwr_sts & pwr_mask) == pwr_mask)
 430                        break;
 431                else
 432                        udelay(10);
 433        }
 434        return 0;
 435}
 436
 437/*
 438 * oaktrail_power_up
 439 *
 440 * Restore power to the specified island(s) (powergating)
 441 */
 442static int oaktrail_power_up(struct drm_device *dev)
 443{
 444        struct drm_psb_private *dev_priv = dev->dev_private;
 445        u32 pwr_mask = PSB_PWRGT_DISPLAY_MASK;
 446        u32 pwr_sts, pwr_cnt;
 447
 448        pwr_cnt = inl(dev_priv->ospm_base + PSB_PM_SSC);
 449        pwr_cnt &= ~pwr_mask;
 450        outl(pwr_cnt, (dev_priv->ospm_base + PSB_PM_SSC));
 451
 452        while (true) {
 453                pwr_sts = inl(dev_priv->ospm_base + PSB_PM_SSS);
 454                if ((pwr_sts & pwr_mask) == 0)
 455                        break;
 456                else
 457                        udelay(10);
 458        }
 459        return 0;
 460}
 461
 462/* Oaktrail */
 463static const struct psb_offset oaktrail_regmap[2] = {
 464        {
 465                .fp0 = MRST_FPA0,
 466                .fp1 = MRST_FPA1,
 467                .cntr = DSPACNTR,
 468                .conf = PIPEACONF,
 469                .src = PIPEASRC,
 470                .dpll = MRST_DPLL_A,
 471                .htotal = HTOTAL_A,
 472                .hblank = HBLANK_A,
 473                .hsync = HSYNC_A,
 474                .vtotal = VTOTAL_A,
 475                .vblank = VBLANK_A,
 476                .vsync = VSYNC_A,
 477                .stride = DSPASTRIDE,
 478                .size = DSPASIZE,
 479                .pos = DSPAPOS,
 480                .surf = DSPASURF,
 481                .addr = MRST_DSPABASE,
 482                .base = MRST_DSPABASE,
 483                .status = PIPEASTAT,
 484                .linoff = DSPALINOFF,
 485                .tileoff = DSPATILEOFF,
 486                .palette = PALETTE_A,
 487        },
 488        {
 489                .fp0 = FPB0,
 490                .fp1 = FPB1,
 491                .cntr = DSPBCNTR,
 492                .conf = PIPEBCONF,
 493                .src = PIPEBSRC,
 494                .dpll = DPLL_B,
 495                .htotal = HTOTAL_B,
 496                .hblank = HBLANK_B,
 497                .hsync = HSYNC_B,
 498                .vtotal = VTOTAL_B,
 499                .vblank = VBLANK_B,
 500                .vsync = VSYNC_B,
 501                .stride = DSPBSTRIDE,
 502                .size = DSPBSIZE,
 503                .pos = DSPBPOS,
 504                .surf = DSPBSURF,
 505                .addr = DSPBBASE,
 506                .base = DSPBBASE,
 507                .status = PIPEBSTAT,
 508                .linoff = DSPBLINOFF,
 509                .tileoff = DSPBTILEOFF,
 510                .palette = PALETTE_B,
 511        },
 512};
 513
 514static int oaktrail_chip_setup(struct drm_device *dev)
 515{
 516        struct drm_psb_private *dev_priv = dev->dev_private;
 517        int ret;
 518        
 519        if (pci_enable_msi(dev->pdev))
 520                dev_warn(dev->dev, "Enabling MSI failed!\n");
 521
 522        dev_priv->regmap = oaktrail_regmap;
 523
 524        ret = mid_chip_setup(dev);
 525        if (ret < 0)
 526                return ret;
 527        if (!dev_priv->has_gct) {
 528                /* Now pull the BIOS data */
 529                psb_intel_opregion_init(dev);
 530                psb_intel_init_bios(dev);
 531        }
 532        gma_intel_setup_gmbus(dev);
 533        oaktrail_hdmi_setup(dev);
 534        return 0;
 535}
 536
 537static void oaktrail_teardown(struct drm_device *dev)
 538{
 539        struct drm_psb_private *dev_priv = dev->dev_private;
 540
 541        gma_intel_teardown_gmbus(dev);
 542        oaktrail_hdmi_teardown(dev);
 543        if (!dev_priv->has_gct)
 544                psb_intel_destroy_bios(dev);
 545}
 546
 547const struct psb_ops oaktrail_chip_ops = {
 548        .name = "Oaktrail",
 549        .accel_2d = 1,
 550        .pipes = 2,
 551        .crtcs = 2,
 552        .hdmi_mask = (1 << 1),
 553        .lvds_mask = (1 << 0),
 554        .sdvo_mask = (1 << 1),
 555        .cursor_needs_phys = 0,
 556        .sgx_offset = MRST_SGX_OFFSET,
 557
 558        .chip_setup = oaktrail_chip_setup,
 559        .chip_teardown = oaktrail_teardown,
 560        .crtc_helper = &oaktrail_helper_funcs,
 561        .crtc_funcs = &psb_intel_crtc_funcs,
 562
 563        .output_init = oaktrail_output_init,
 564
 565#ifdef CONFIG_BACKLIGHT_CLASS_DEVICE
 566        .backlight_init = oaktrail_backlight_init,
 567#endif
 568
 569        .save_regs = oaktrail_save_display_registers,
 570        .restore_regs = oaktrail_restore_display_registers,
 571        .save_crtc = gma_crtc_save,
 572        .restore_crtc = gma_crtc_restore,
 573        .power_down = oaktrail_power_down,
 574        .power_up = oaktrail_power_up,
 575
 576        .i2c_bus = 1,
 577};
 578