wl1251: experimental PS hacks
[pandora-kernel.git] / drivers / staging / gma500 / mrst_device.c
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 "psb_drm.h"
26 #include "psb_drv.h"
27 #include "psb_reg.h"
28 #include "psb_intel_reg.h"
29 #include <asm/mrst.h>
30 #include <asm/intel_scu_ipc.h>
31 #include "mid_bios.h"
32
33 static int devtype;
34
35 module_param_named(type, devtype, int, 0600);
36 MODULE_PARM_DESC(type, "Moorestown/Oaktrail device type");
37
38 #define DEVICE_MOORESTOWN               1
39 #define DEVICE_OAKTRAIL                 2
40 #define DEVICE_MOORESTOWN_MM            3
41
42 static int mrst_device_ident(struct drm_device *dev)
43 {
44         /* User forced */
45         if (devtype)
46                 return devtype;
47         if (dmi_match(DMI_PRODUCT_NAME, "OakTrail") ||
48                 dmi_match(DMI_PRODUCT_NAME, "OakTrail platform"))
49                 return DEVICE_OAKTRAIL;
50 #if defined(CONFIG_X86_MRST)
51         if (dmi_match(DMI_PRODUCT_NAME, "MM") ||
52                 dmi_match(DMI_PRODUCT_NAME, "MM 10"))
53                 return DEVICE_MOORESTOWN_MM;
54         if (mrst_identify_cpu())
55                 return DEVICE_MOORESTOWN;
56 #endif
57         return DEVICE_OAKTRAIL;
58 }
59
60
61 /* IPC message and command defines used to enable/disable mipi panel voltages */
62 #define IPC_MSG_PANEL_ON_OFF    0xE9
63 #define IPC_CMD_PANEL_ON        1
64 #define IPC_CMD_PANEL_OFF       0
65
66 static int mrst_output_init(struct drm_device *dev)
67 {
68         struct drm_psb_private *dev_priv = dev->dev_private;
69         if (dev_priv->iLVDS_enable)
70                 mrst_lvds_init(dev, &dev_priv->mode_dev);
71         else
72                 dev_err(dev->dev, "DSI is not supported\n");
73         if (dev_priv->hdmi_priv)
74                 mrst_hdmi_init(dev, &dev_priv->mode_dev);
75         return 0;
76 }
77
78 /*
79  *      Provide the low level interfaces for the Moorestown backlight
80  */
81
82 #ifdef CONFIG_BACKLIGHT_CLASS_DEVICE
83
84 #define MRST_BLC_MAX_PWM_REG_FREQ           0xFFFF
85 #define BLC_PWM_PRECISION_FACTOR 100    /* 10000000 */
86 #define BLC_PWM_FREQ_CALC_CONSTANT 32
87 #define MHz 1000000
88 #define BLC_ADJUSTMENT_MAX 100
89
90 static struct backlight_device *mrst_backlight_device;
91 static int mrst_brightness;
92
93 static int mrst_set_brightness(struct backlight_device *bd)
94 {
95         struct drm_device *dev = bl_get_data(mrst_backlight_device);
96         struct drm_psb_private *dev_priv = dev->dev_private;
97         int level = bd->props.brightness;
98         u32 blc_pwm_ctl;
99         u32 max_pwm_blc;
100
101         /* Percentage 1-100% being valid */
102         if (level < 1)
103                 level = 1;
104
105         if (gma_power_begin(dev, 0)) {
106                 /* Calculate and set the brightness value */
107                 max_pwm_blc = REG_READ(BLC_PWM_CTL) >> 16;
108                 blc_pwm_ctl = level * max_pwm_blc / 100;
109
110                 /* Adjust the backlight level with the percent in
111                  * dev_priv->blc_adj1;
112                  */
113                 blc_pwm_ctl = blc_pwm_ctl * dev_priv->blc_adj1;
114                 blc_pwm_ctl = blc_pwm_ctl / 100;
115
116                 /* Adjust the backlight level with the percent in
117                  * dev_priv->blc_adj2;
118                  */
119                 blc_pwm_ctl = blc_pwm_ctl * dev_priv->blc_adj2;
120                 blc_pwm_ctl = blc_pwm_ctl / 100;
121
122                 /* force PWM bit on */
123                 REG_WRITE(BLC_PWM_CTL2, (0x80000000 | REG_READ(BLC_PWM_CTL2)));
124                 REG_WRITE(BLC_PWM_CTL, (max_pwm_blc << 16) | blc_pwm_ctl);
125                 gma_power_end(dev);
126         }
127         mrst_brightness = level;
128         return 0;
129 }
130
131 static int mrst_get_brightness(struct backlight_device *bd)
132 {
133         /* return locally cached var instead of HW read (due to DPST etc.) */
134         /* FIXME: ideally return actual value in case firmware fiddled with
135            it */
136         return mrst_brightness;
137 }
138
139 static int device_backlight_init(struct drm_device *dev)
140 {
141         struct drm_psb_private *dev_priv = dev->dev_private;
142         unsigned long core_clock;
143         u16 bl_max_freq;
144         uint32_t value;
145         uint32_t blc_pwm_precision_factor;
146
147         dev_priv->blc_adj1 = BLC_ADJUSTMENT_MAX;
148         dev_priv->blc_adj2 = BLC_ADJUSTMENT_MAX;
149         bl_max_freq = 256;
150         /* this needs to be set elsewhere */
151         blc_pwm_precision_factor = BLC_PWM_PRECISION_FACTOR;
152
153         core_clock = dev_priv->core_freq;
154
155         value = (core_clock * MHz) / BLC_PWM_FREQ_CALC_CONSTANT;
156         value *= blc_pwm_precision_factor;
157         value /= bl_max_freq;
158         value /= blc_pwm_precision_factor;
159
160         if (value > (unsigned long long)MRST_BLC_MAX_PWM_REG_FREQ)
161                         return -ERANGE;
162
163         if (gma_power_begin(dev, false)) {
164                 REG_WRITE(BLC_PWM_CTL2, (0x80000000 | REG_READ(BLC_PWM_CTL2)));
165                 REG_WRITE(BLC_PWM_CTL, value | (value << 16));
166                 gma_power_end(dev);
167         }
168         return 0;
169 }
170
171 static const struct backlight_ops mrst_ops = {
172         .get_brightness = mrst_get_brightness,
173         .update_status  = mrst_set_brightness,
174 };
175
176 int mrst_backlight_init(struct drm_device *dev)
177 {
178         struct drm_psb_private *dev_priv = dev->dev_private;
179         int ret;
180         struct backlight_properties props;
181
182         memset(&props, 0, sizeof(struct backlight_properties));
183         props.max_brightness = 100;
184         props.type = BACKLIGHT_PLATFORM;
185
186         mrst_backlight_device = backlight_device_register("mrst-bl",
187                                         NULL, (void *)dev, &mrst_ops, &props);
188
189         if (IS_ERR(mrst_backlight_device))
190                 return PTR_ERR(mrst_backlight_device);
191
192         ret = device_backlight_init(dev);
193         if (ret < 0) {
194                 backlight_device_unregister(mrst_backlight_device);
195                 return ret;
196         }
197         mrst_backlight_device->props.brightness = 100;
198         mrst_backlight_device->props.max_brightness = 100;
199         backlight_update_status(mrst_backlight_device);
200         dev_priv->backlight_device = mrst_backlight_device;
201         return 0;
202 }
203
204 #endif
205
206 /*
207  *      Provide the Moorestown specific chip logic and low level methods
208  *      for power management
209  */
210
211 static void mrst_init_pm(struct drm_device *dev)
212 {
213 }
214
215 /**
216  *      mrst_save_display_registers     -       save registers lost on suspend
217  *      @dev: our DRM device
218  *
219  *      Save the state we need in order to be able to restore the interface
220  *      upon resume from suspend
221  */
222 static int mrst_save_display_registers(struct drm_device *dev)
223 {
224         struct drm_psb_private *dev_priv = dev->dev_private;
225         int i;
226         u32 pp_stat;
227
228         /* Display arbitration control + watermarks */
229         dev_priv->saveDSPARB = PSB_RVDC32(DSPARB);
230         dev_priv->saveDSPFW1 = PSB_RVDC32(DSPFW1);
231         dev_priv->saveDSPFW2 = PSB_RVDC32(DSPFW2);
232         dev_priv->saveDSPFW3 = PSB_RVDC32(DSPFW3);
233         dev_priv->saveDSPFW4 = PSB_RVDC32(DSPFW4);
234         dev_priv->saveDSPFW5 = PSB_RVDC32(DSPFW5);
235         dev_priv->saveDSPFW6 = PSB_RVDC32(DSPFW6);
236         dev_priv->saveCHICKENBIT = PSB_RVDC32(DSPCHICKENBIT);
237
238         /* Pipe & plane A info */
239         dev_priv->savePIPEACONF = PSB_RVDC32(PIPEACONF);
240         dev_priv->savePIPEASRC = PSB_RVDC32(PIPEASRC);
241         dev_priv->saveFPA0 = PSB_RVDC32(MRST_FPA0);
242         dev_priv->saveFPA1 = PSB_RVDC32(MRST_FPA1);
243         dev_priv->saveDPLL_A = PSB_RVDC32(MRST_DPLL_A);
244         dev_priv->saveHTOTAL_A = PSB_RVDC32(HTOTAL_A);
245         dev_priv->saveHBLANK_A = PSB_RVDC32(HBLANK_A);
246         dev_priv->saveHSYNC_A = PSB_RVDC32(HSYNC_A);
247         dev_priv->saveVTOTAL_A = PSB_RVDC32(VTOTAL_A);
248         dev_priv->saveVBLANK_A = PSB_RVDC32(VBLANK_A);
249         dev_priv->saveVSYNC_A = PSB_RVDC32(VSYNC_A);
250         dev_priv->saveBCLRPAT_A = PSB_RVDC32(BCLRPAT_A);
251         dev_priv->saveDSPACNTR = PSB_RVDC32(DSPACNTR);
252         dev_priv->saveDSPASTRIDE = PSB_RVDC32(DSPASTRIDE);
253         dev_priv->saveDSPAADDR = PSB_RVDC32(DSPABASE);
254         dev_priv->saveDSPASURF = PSB_RVDC32(DSPASURF);
255         dev_priv->saveDSPALINOFF = PSB_RVDC32(DSPALINOFF);
256         dev_priv->saveDSPATILEOFF = PSB_RVDC32(DSPATILEOFF);
257
258         /* Save cursor regs */
259         dev_priv->saveDSPACURSOR_CTRL = PSB_RVDC32(CURACNTR);
260         dev_priv->saveDSPACURSOR_BASE = PSB_RVDC32(CURABASE);
261         dev_priv->saveDSPACURSOR_POS = PSB_RVDC32(CURAPOS);
262
263         /* Save palette (gamma) */
264         for (i = 0; i < 256; i++)
265                 dev_priv->save_palette_a[i] = PSB_RVDC32(PALETTE_A + (i << 2));
266
267         if (dev_priv->hdmi_priv)
268                 mrst_hdmi_save(dev);
269
270         /* Save performance state */
271         dev_priv->savePERF_MODE = PSB_RVDC32(MRST_PERF_MODE);
272
273         /* LVDS state */
274         dev_priv->savePP_CONTROL = PSB_RVDC32(PP_CONTROL);
275         dev_priv->savePFIT_PGM_RATIOS = PSB_RVDC32(PFIT_PGM_RATIOS);
276         dev_priv->savePFIT_AUTO_RATIOS = PSB_RVDC32(PFIT_AUTO_RATIOS);
277         dev_priv->saveBLC_PWM_CTL = PSB_RVDC32(BLC_PWM_CTL);
278         dev_priv->saveBLC_PWM_CTL2 = PSB_RVDC32(BLC_PWM_CTL2);
279         dev_priv->saveLVDS = PSB_RVDC32(LVDS);
280         dev_priv->savePFIT_CONTROL = PSB_RVDC32(PFIT_CONTROL);
281         dev_priv->savePP_ON_DELAYS = PSB_RVDC32(LVDSPP_ON);
282         dev_priv->savePP_OFF_DELAYS = PSB_RVDC32(LVDSPP_OFF);
283         dev_priv->savePP_DIVISOR = PSB_RVDC32(PP_CYCLE);
284
285         /* HW overlay */
286         dev_priv->saveOV_OVADD = PSB_RVDC32(OV_OVADD);
287         dev_priv->saveOV_OGAMC0 = PSB_RVDC32(OV_OGAMC0);
288         dev_priv->saveOV_OGAMC1 = PSB_RVDC32(OV_OGAMC1);
289         dev_priv->saveOV_OGAMC2 = PSB_RVDC32(OV_OGAMC2);
290         dev_priv->saveOV_OGAMC3 = PSB_RVDC32(OV_OGAMC3);
291         dev_priv->saveOV_OGAMC4 = PSB_RVDC32(OV_OGAMC4);
292         dev_priv->saveOV_OGAMC5 = PSB_RVDC32(OV_OGAMC5);
293
294         /* DPST registers */
295         dev_priv->saveHISTOGRAM_INT_CONTROL_REG =
296                                         PSB_RVDC32(HISTOGRAM_INT_CONTROL);
297         dev_priv->saveHISTOGRAM_LOGIC_CONTROL_REG =
298                                         PSB_RVDC32(HISTOGRAM_LOGIC_CONTROL);
299         dev_priv->savePWM_CONTROL_LOGIC = PSB_RVDC32(PWM_CONTROL_LOGIC);
300
301         if (dev_priv->iLVDS_enable) {
302                 /* Shut down the panel */
303                 PSB_WVDC32(0, PP_CONTROL);
304
305                 do {
306                         pp_stat = PSB_RVDC32(PP_STATUS);
307                 } while (pp_stat & 0x80000000);
308
309                 /* Turn off the plane */
310                 PSB_WVDC32(0x58000000, DSPACNTR);
311                 /* Trigger the plane disable */
312                 PSB_WVDC32(0, DSPASURF);
313
314                 /* Wait ~4 ticks */
315                 msleep(4);
316
317                 /* Turn off pipe */
318                 PSB_WVDC32(0x0, PIPEACONF);
319                 /* Wait ~8 ticks */
320                 msleep(8);
321
322                 /* Turn off PLLs */
323                 PSB_WVDC32(0, MRST_DPLL_A);
324         }
325         return 0;
326 }
327
328 /**
329  *      mrst_restore_display_registers  -       restore lost register state
330  *      @dev: our DRM device
331  *
332  *      Restore register state that was lost during suspend and resume.
333  */
334 static int mrst_restore_display_registers(struct drm_device *dev)
335 {
336         struct drm_psb_private *dev_priv = dev->dev_private;
337         u32 pp_stat;
338         int i;
339
340         /* Display arbitration + watermarks */
341         PSB_WVDC32(dev_priv->saveDSPARB, DSPARB);
342         PSB_WVDC32(dev_priv->saveDSPFW1, DSPFW1);
343         PSB_WVDC32(dev_priv->saveDSPFW2, DSPFW2);
344         PSB_WVDC32(dev_priv->saveDSPFW3, DSPFW3);
345         PSB_WVDC32(dev_priv->saveDSPFW4, DSPFW4);
346         PSB_WVDC32(dev_priv->saveDSPFW5, DSPFW5);
347         PSB_WVDC32(dev_priv->saveDSPFW6, DSPFW6);
348         PSB_WVDC32(dev_priv->saveCHICKENBIT, DSPCHICKENBIT);
349
350         /* Make sure VGA plane is off. it initializes to on after reset!*/
351         PSB_WVDC32(0x80000000, VGACNTRL);
352
353         /* set the plls */
354         PSB_WVDC32(dev_priv->saveFPA0, MRST_FPA0);
355         PSB_WVDC32(dev_priv->saveFPA1, MRST_FPA1);
356
357         /* Actually enable it */
358         PSB_WVDC32(dev_priv->saveDPLL_A, MRST_DPLL_A);
359         DRM_UDELAY(150);
360
361         /* Restore mode */
362         PSB_WVDC32(dev_priv->saveHTOTAL_A, HTOTAL_A);
363         PSB_WVDC32(dev_priv->saveHBLANK_A, HBLANK_A);
364         PSB_WVDC32(dev_priv->saveHSYNC_A, HSYNC_A);
365         PSB_WVDC32(dev_priv->saveVTOTAL_A, VTOTAL_A);
366         PSB_WVDC32(dev_priv->saveVBLANK_A, VBLANK_A);
367         PSB_WVDC32(dev_priv->saveVSYNC_A, VSYNC_A);
368         PSB_WVDC32(dev_priv->savePIPEASRC, PIPEASRC);
369         PSB_WVDC32(dev_priv->saveBCLRPAT_A, BCLRPAT_A);
370
371         /* Restore performance mode*/
372         PSB_WVDC32(dev_priv->savePERF_MODE, MRST_PERF_MODE);
373
374         /* Enable the pipe*/
375         if (dev_priv->iLVDS_enable)
376                 PSB_WVDC32(dev_priv->savePIPEACONF, PIPEACONF);
377
378         /* Set up the plane*/
379         PSB_WVDC32(dev_priv->saveDSPALINOFF, DSPALINOFF);
380         PSB_WVDC32(dev_priv->saveDSPASTRIDE, DSPASTRIDE);
381         PSB_WVDC32(dev_priv->saveDSPATILEOFF, DSPATILEOFF);
382
383         /* Enable the plane */
384         PSB_WVDC32(dev_priv->saveDSPACNTR, DSPACNTR);
385         PSB_WVDC32(dev_priv->saveDSPASURF, DSPASURF);
386
387         /* Enable Cursor A */
388         PSB_WVDC32(dev_priv->saveDSPACURSOR_CTRL, CURACNTR);
389         PSB_WVDC32(dev_priv->saveDSPACURSOR_POS, CURAPOS);
390         PSB_WVDC32(dev_priv->saveDSPACURSOR_BASE, CURABASE);
391
392         /* Restore palette (gamma) */
393         for (i = 0; i < 256; i++)
394                 PSB_WVDC32(dev_priv->save_palette_a[i], PALETTE_A + (i << 2));
395
396         if (dev_priv->hdmi_priv)
397                 mrst_hdmi_restore(dev);
398
399         if (dev_priv->iLVDS_enable) {
400                 PSB_WVDC32(dev_priv->saveBLC_PWM_CTL2, BLC_PWM_CTL2);
401                 PSB_WVDC32(dev_priv->saveLVDS, LVDS); /*port 61180h*/
402                 PSB_WVDC32(dev_priv->savePFIT_CONTROL, PFIT_CONTROL);
403                 PSB_WVDC32(dev_priv->savePFIT_PGM_RATIOS, PFIT_PGM_RATIOS);
404                 PSB_WVDC32(dev_priv->savePFIT_AUTO_RATIOS, PFIT_AUTO_RATIOS);
405                 PSB_WVDC32(dev_priv->saveBLC_PWM_CTL, BLC_PWM_CTL);
406                 PSB_WVDC32(dev_priv->savePP_ON_DELAYS, LVDSPP_ON);
407                 PSB_WVDC32(dev_priv->savePP_OFF_DELAYS, LVDSPP_OFF);
408                 PSB_WVDC32(dev_priv->savePP_DIVISOR, PP_CYCLE);
409                 PSB_WVDC32(dev_priv->savePP_CONTROL, PP_CONTROL);
410         }
411
412         /* Wait for cycle delay */
413         do {
414                 pp_stat = PSB_RVDC32(PP_STATUS);
415         } while (pp_stat & 0x08000000);
416
417         /* Wait for panel power up */
418         do {
419                 pp_stat = PSB_RVDC32(PP_STATUS);
420         } while (pp_stat & 0x10000000);
421
422         /* Restore HW overlay */
423         PSB_WVDC32(dev_priv->saveOV_OVADD, OV_OVADD);
424         PSB_WVDC32(dev_priv->saveOV_OGAMC0, OV_OGAMC0);
425         PSB_WVDC32(dev_priv->saveOV_OGAMC1, OV_OGAMC1);
426         PSB_WVDC32(dev_priv->saveOV_OGAMC2, OV_OGAMC2);
427         PSB_WVDC32(dev_priv->saveOV_OGAMC3, OV_OGAMC3);
428         PSB_WVDC32(dev_priv->saveOV_OGAMC4, OV_OGAMC4);
429         PSB_WVDC32(dev_priv->saveOV_OGAMC5, OV_OGAMC5);
430
431         /* DPST registers */
432         PSB_WVDC32(dev_priv->saveHISTOGRAM_INT_CONTROL_REG,
433                                                 HISTOGRAM_INT_CONTROL);
434         PSB_WVDC32(dev_priv->saveHISTOGRAM_LOGIC_CONTROL_REG,
435                                                 HISTOGRAM_LOGIC_CONTROL);
436         PSB_WVDC32(dev_priv->savePWM_CONTROL_LOGIC, PWM_CONTROL_LOGIC);
437
438         return 0;
439 }
440
441 /**
442  *      mrst_power_down -       power down the display island
443  *      @dev: our DRM device
444  *
445  *      Power down the display interface of our device
446  */
447 static int mrst_power_down(struct drm_device *dev)
448 {
449         struct drm_psb_private *dev_priv = dev->dev_private;
450         u32 pwr_mask ;
451         u32 pwr_sts;
452
453         pwr_mask = PSB_PWRGT_DISPLAY_MASK;
454         outl(pwr_mask, dev_priv->ospm_base + PSB_PM_SSC);
455
456         while (true) {
457                 pwr_sts = inl(dev_priv->ospm_base + PSB_PM_SSS);
458                 if ((pwr_sts & pwr_mask) == pwr_mask)
459                         break;
460                 else
461                         udelay(10);
462         }
463         return 0;
464 }
465
466 /*
467  * mrst_power_up
468  *
469  * Restore power to the specified island(s) (powergating)
470  */
471 static int mrst_power_up(struct drm_device *dev)
472 {
473         struct drm_psb_private *dev_priv = dev->dev_private;
474         u32 pwr_mask = PSB_PWRGT_DISPLAY_MASK;
475         u32 pwr_sts, pwr_cnt;
476
477         pwr_cnt = inl(dev_priv->ospm_base + PSB_PM_SSC);
478         pwr_cnt &= ~pwr_mask;
479         outl(pwr_cnt, (dev_priv->ospm_base + PSB_PM_SSC));
480
481         while (true) {
482                 pwr_sts = inl(dev_priv->ospm_base + PSB_PM_SSS);
483                 if ((pwr_sts & pwr_mask) == 0)
484                         break;
485                 else
486                         udelay(10);
487         }
488         return 0;
489 }
490
491 #if defined(CONFIG_X86_MRST)
492 static void mrst_lvds_cache_bl(struct drm_device *dev)
493 {
494         struct drm_psb_private *dev_priv = dev->dev_private;
495
496         intel_scu_ipc_ioread8(0x28, &(dev_priv->saveBKLTCNT));
497         intel_scu_ipc_ioread8(0x29, &(dev_priv->saveBKLTREQ));
498         intel_scu_ipc_ioread8(0x2A, &(dev_priv->saveBKLTBRTL));
499 }
500
501 static void mrst_mm_bl_power(struct drm_device *dev, bool on)
502 {
503         struct drm_psb_private *dev_priv = dev->dev_private;
504
505         if (on) {
506                 intel_scu_ipc_iowrite8(0x2A, dev_priv->saveBKLTBRTL);
507                 intel_scu_ipc_iowrite8(0x28, dev_priv->saveBKLTCNT);
508                 intel_scu_ipc_iowrite8(0x29, dev_priv->saveBKLTREQ);
509         } else {
510                 intel_scu_ipc_iowrite8(0x2A, 0);
511                 intel_scu_ipc_iowrite8(0x28, 0);
512                 intel_scu_ipc_iowrite8(0x29, 0);
513         }
514 }
515
516 static const struct psb_ops mrst_mm_chip_ops = {
517         .name = "Moorestown MM ",
518         .accel_2d = 1,
519         .pipes = 1,
520         .crtcs = 1,
521         .sgx_offset = MRST_SGX_OFFSET,
522
523         .crtc_helper = &mrst_helper_funcs,
524         .crtc_funcs = &psb_intel_crtc_funcs,
525
526         .output_init = mrst_output_init,
527
528         .lvds_bl_power = mrst_mm_bl_power,
529 #ifdef CONFIG_BACKLIGHT_CLASS_DEVICE
530         .backlight_init = mrst_backlight_init,
531 #endif
532
533         .init_pm = mrst_init_pm,
534         .save_regs = mrst_save_display_registers,
535         .restore_regs = mrst_restore_display_registers,
536         .power_down = mrst_power_down,
537         .power_up = mrst_power_up,
538
539         .i2c_bus = 0,
540 };
541
542 #endif
543
544 static void oaktrail_teardown(struct drm_device *dev)
545 {
546         mrst_hdmi_teardown(dev);
547 }
548
549 static const struct psb_ops oaktrail_chip_ops = {
550         .name = "Oaktrail",
551         .accel_2d = 1,
552         .pipes = 2,
553         .crtcs = 2,
554         .sgx_offset = MRST_SGX_OFFSET,
555
556         .chip_setup = mid_chip_setup,
557         .chip_teardown = oaktrail_teardown,
558         .crtc_helper = &mrst_helper_funcs,
559         .crtc_funcs = &psb_intel_crtc_funcs,
560
561         .output_init = mrst_output_init,
562
563 #ifdef CONFIG_BACKLIGHT_CLASS_DEVICE
564         .backlight_init = mrst_backlight_init,
565 #endif
566
567         .init_pm = mrst_init_pm,
568         .save_regs = mrst_save_display_registers,
569         .restore_regs = mrst_restore_display_registers,
570         .power_down = mrst_power_down,
571         .power_up = mrst_power_up,
572
573         .i2c_bus = 1,
574 };
575
576 /**
577  *      mrst_chip_setup         -       perform the initial chip init
578  *      @dev: Our drm_device
579  *
580  *      Figure out which incarnation we are and then scan the firmware for
581  *      tables and information.
582  */
583 static int mrst_chip_setup(struct drm_device *dev)
584 {
585         struct drm_psb_private *dev_priv = dev->dev_private;
586
587         switch (mrst_device_ident(dev)) {
588         case DEVICE_OAKTRAIL:
589                 /* Dual CRTC, PC compatible, HDMI, I2C #2 */
590                 dev_priv->ops = &oaktrail_chip_ops;
591                 mrst_hdmi_setup(dev);
592                 return mid_chip_setup(dev);
593 #if defined(CONFIG_X86_MRST)
594         case DEVICE_MOORESTOWN_MM:
595                 /* Single CRTC, No HDMI, I2C #0, BL control */
596                 mrst_lvds_cache_bl(dev);
597                 dev_priv->ops = &mrst_mm_chip_ops;
598                 return mid_chip_setup(dev);
599         case DEVICE_MOORESTOWN:
600                 /* Dual CRTC, No HDMI(?), I2C #1 */
601                 return mid_chip_setup(dev);
602 #endif
603         default:
604                 dev_err(dev->dev, "unsupported device type.\n");
605                 return -ENODEV;
606         }
607 }
608
609 const struct psb_ops mrst_chip_ops = {
610         .name = "Moorestown",
611         .accel_2d = 1,
612         .pipes = 2,
613         .crtcs = 2,
614         .sgx_offset = MRST_SGX_OFFSET,
615
616         .chip_setup = mrst_chip_setup,
617         .crtc_helper = &mrst_helper_funcs,
618         .crtc_funcs = &psb_intel_crtc_funcs,
619
620         .output_init = mrst_output_init,
621
622 #ifdef CONFIG_BACKLIGHT_CLASS_DEVICE
623         .backlight_init = mrst_backlight_init,
624 #endif
625
626         .init_pm = mrst_init_pm,
627         .save_regs = mrst_save_display_registers,
628         .restore_regs = mrst_restore_display_registers,
629         .power_down = mrst_power_down,
630         .power_up = mrst_power_up,
631
632         .i2c_bus = 2,
633 };
634