gma500: More Moorestown muddle meddling means MM maybe might modeset
[linux-2.6/linux-acpi-2.6/ibm-acpi-2.6.git] / drivers / staging / gma500 / mrst_device.c
blob573142f13f83d20e3bd857f17ea40e1d2c25b241
1 /**************************************************************************
2 * Copyright (c) 2011, Intel Corporation.
3 * All Rights Reserved.
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.
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.
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.
18 **************************************************************************/
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"
33 static int devtype;
35 module_param_named(type, devtype, int, 0600);
36 MODULE_PARM_DESC(type, "Moorestown/Oaktrail device type");
38 #define DEVICE_MOORESTOWN 1
39 #define DEVICE_OAKTRAIL 2
40 #define DEVICE_MOORESTOWN_MM 3
42 static int mrst_device_ident(struct drm_device *dev)
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;
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
66 static int mrst_output_init(struct drm_device *dev)
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;
79 * Provide the low level interfaces for the Moorestown backlight
82 #ifdef CONFIG_BACKLIGHT_CLASS_DEVICE
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
90 static struct backlight_device *mrst_backlight_device;
91 static int mrst_brightness;
93 static int mrst_set_brightness(struct backlight_device *bd)
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;
101 /* Percentage 1-100% being valid */
102 if (level < 1)
103 level = 1;
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;
110 /* Adjust the backlight level with the percent in
111 * dev_priv->blc_adj1;
113 blc_pwm_ctl = blc_pwm_ctl * dev_priv->blc_adj1;
114 blc_pwm_ctl = blc_pwm_ctl / 100;
116 /* Adjust the backlight level with the percent in
117 * dev_priv->blc_adj2;
119 blc_pwm_ctl = blc_pwm_ctl * dev_priv->blc_adj2;
120 blc_pwm_ctl = blc_pwm_ctl / 100;
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);
127 mrst_brightness = level;
128 return 0;
131 static int mrst_get_brightness(struct backlight_device *bd)
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;
139 static int device_backlight_init(struct drm_device *dev)
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;
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;
153 core_clock = dev_priv->core_freq;
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;
160 if (gma_power_begin(dev, false)) {
161 if (value > (unsigned long long)MRST_BLC_MAX_PWM_REG_FREQ)
162 return -ERANGE;
163 else {
164 REG_WRITE(BLC_PWM_CTL2,
165 (0x80000000 | REG_READ(BLC_PWM_CTL2)));
166 REG_WRITE(BLC_PWM_CTL, value | (value << 16));
168 gma_power_end(dev);
170 return 0;
173 static const struct backlight_ops mrst_ops = {
174 .get_brightness = mrst_get_brightness,
175 .update_status = mrst_set_brightness,
178 int mrst_backlight_init(struct drm_device *dev)
180 struct drm_psb_private *dev_priv = dev->dev_private;
181 int ret;
182 struct backlight_properties props;
184 memset(&props, 0, sizeof(struct backlight_properties));
185 props.max_brightness = 100;
186 props.type = BACKLIGHT_PLATFORM;
188 mrst_backlight_device = backlight_device_register("mrst-bl",
189 NULL, (void *)dev, &mrst_ops, &props);
191 if (IS_ERR(mrst_backlight_device))
192 return PTR_ERR(mrst_backlight_device);
194 ret = device_backlight_init(dev);
195 if (ret < 0) {
196 backlight_device_unregister(mrst_backlight_device);
197 return ret;
199 mrst_backlight_device->props.brightness = 100;
200 mrst_backlight_device->props.max_brightness = 100;
201 backlight_update_status(mrst_backlight_device);
202 dev_priv->backlight_device = mrst_backlight_device;
203 return 0;
206 #endif
209 * Provide the Moorestown specific chip logic and low level methods
210 * for power management
213 static void mrst_init_pm(struct drm_device *dev)
218 * mrst_save_display_registers - save registers lost on suspend
219 * @dev: our DRM device
221 * Save the state we need in order to be able to restore the interface
222 * upon resume from suspend
224 static int mrst_save_display_registers(struct drm_device *dev)
226 struct drm_psb_private *dev_priv = dev->dev_private;
227 int i;
228 u32 pp_stat;
230 /* Display arbitration control + watermarks */
231 dev_priv->saveDSPARB = PSB_RVDC32(DSPARB);
232 dev_priv->saveDSPFW1 = PSB_RVDC32(DSPFW1);
233 dev_priv->saveDSPFW2 = PSB_RVDC32(DSPFW2);
234 dev_priv->saveDSPFW3 = PSB_RVDC32(DSPFW3);
235 dev_priv->saveDSPFW4 = PSB_RVDC32(DSPFW4);
236 dev_priv->saveDSPFW5 = PSB_RVDC32(DSPFW5);
237 dev_priv->saveDSPFW6 = PSB_RVDC32(DSPFW6);
238 dev_priv->saveCHICKENBIT = PSB_RVDC32(DSPCHICKENBIT);
240 /* Pipe & plane A info */
241 dev_priv->savePIPEACONF = PSB_RVDC32(PIPEACONF);
242 dev_priv->savePIPEASRC = PSB_RVDC32(PIPEASRC);
243 dev_priv->saveFPA0 = PSB_RVDC32(MRST_FPA0);
244 dev_priv->saveFPA1 = PSB_RVDC32(MRST_FPA1);
245 dev_priv->saveDPLL_A = PSB_RVDC32(MRST_DPLL_A);
246 dev_priv->saveHTOTAL_A = PSB_RVDC32(HTOTAL_A);
247 dev_priv->saveHBLANK_A = PSB_RVDC32(HBLANK_A);
248 dev_priv->saveHSYNC_A = PSB_RVDC32(HSYNC_A);
249 dev_priv->saveVTOTAL_A = PSB_RVDC32(VTOTAL_A);
250 dev_priv->saveVBLANK_A = PSB_RVDC32(VBLANK_A);
251 dev_priv->saveVSYNC_A = PSB_RVDC32(VSYNC_A);
252 dev_priv->saveBCLRPAT_A = PSB_RVDC32(BCLRPAT_A);
253 dev_priv->saveDSPACNTR = PSB_RVDC32(DSPACNTR);
254 dev_priv->saveDSPASTRIDE = PSB_RVDC32(DSPASTRIDE);
255 dev_priv->saveDSPAADDR = PSB_RVDC32(DSPABASE);
256 dev_priv->saveDSPASURF = PSB_RVDC32(DSPASURF);
257 dev_priv->saveDSPALINOFF = PSB_RVDC32(DSPALINOFF);
258 dev_priv->saveDSPATILEOFF = PSB_RVDC32(DSPATILEOFF);
260 /* Save cursor regs */
261 dev_priv->saveDSPACURSOR_CTRL = PSB_RVDC32(CURACNTR);
262 dev_priv->saveDSPACURSOR_BASE = PSB_RVDC32(CURABASE);
263 dev_priv->saveDSPACURSOR_POS = PSB_RVDC32(CURAPOS);
265 /* Save palette (gamma) */
266 for (i = 0; i < 256; i++)
267 dev_priv->save_palette_a[i] = PSB_RVDC32(PALETTE_A + (i << 2));
269 if (dev_priv->hdmi_priv)
270 mrst_hdmi_save(dev);
272 /* Save performance state */
273 dev_priv->savePERF_MODE = PSB_RVDC32(MRST_PERF_MODE);
275 /* LVDS state */
276 dev_priv->savePP_CONTROL = PSB_RVDC32(PP_CONTROL);
277 dev_priv->savePFIT_PGM_RATIOS = PSB_RVDC32(PFIT_PGM_RATIOS);
278 dev_priv->savePFIT_AUTO_RATIOS = PSB_RVDC32(PFIT_AUTO_RATIOS);
279 dev_priv->saveBLC_PWM_CTL = PSB_RVDC32(BLC_PWM_CTL);
280 dev_priv->saveBLC_PWM_CTL2 = PSB_RVDC32(BLC_PWM_CTL2);
281 dev_priv->saveLVDS = PSB_RVDC32(LVDS);
282 dev_priv->savePFIT_CONTROL = PSB_RVDC32(PFIT_CONTROL);
283 dev_priv->savePP_ON_DELAYS = PSB_RVDC32(LVDSPP_ON);
284 dev_priv->savePP_OFF_DELAYS = PSB_RVDC32(LVDSPP_OFF);
285 dev_priv->savePP_DIVISOR = PSB_RVDC32(PP_CYCLE);
287 /* HW overlay */
288 dev_priv->saveOV_OVADD = PSB_RVDC32(OV_OVADD);
289 dev_priv->saveOV_OGAMC0 = PSB_RVDC32(OV_OGAMC0);
290 dev_priv->saveOV_OGAMC1 = PSB_RVDC32(OV_OGAMC1);
291 dev_priv->saveOV_OGAMC2 = PSB_RVDC32(OV_OGAMC2);
292 dev_priv->saveOV_OGAMC3 = PSB_RVDC32(OV_OGAMC3);
293 dev_priv->saveOV_OGAMC4 = PSB_RVDC32(OV_OGAMC4);
294 dev_priv->saveOV_OGAMC5 = PSB_RVDC32(OV_OGAMC5);
296 /* DPST registers */
297 dev_priv->saveHISTOGRAM_INT_CONTROL_REG =
298 PSB_RVDC32(HISTOGRAM_INT_CONTROL);
299 dev_priv->saveHISTOGRAM_LOGIC_CONTROL_REG =
300 PSB_RVDC32(HISTOGRAM_LOGIC_CONTROL);
301 dev_priv->savePWM_CONTROL_LOGIC = PSB_RVDC32(PWM_CONTROL_LOGIC);
303 if (dev_priv->iLVDS_enable) {
304 /* Shut down the panel */
305 PSB_WVDC32(0, PP_CONTROL);
307 do {
308 pp_stat = PSB_RVDC32(PP_STATUS);
309 } while (pp_stat & 0x80000000);
311 /* Turn off the plane */
312 PSB_WVDC32(0x58000000, DSPACNTR);
313 /* Trigger the plane disable */
314 PSB_WVDC32(0, DSPASURF);
316 /* Wait ~4 ticks */
317 msleep(4);
319 /* Turn off pipe */
320 PSB_WVDC32(0x0, PIPEACONF);
321 /* Wait ~8 ticks */
322 msleep(8);
324 /* Turn off PLLs */
325 PSB_WVDC32(0, MRST_DPLL_A);
327 return 0;
331 * mrst_restore_display_registers - restore lost register state
332 * @dev: our DRM device
334 * Restore register state that was lost during suspend and resume.
336 static int mrst_restore_display_registers(struct drm_device *dev)
338 struct drm_psb_private *dev_priv = dev->dev_private;
339 u32 pp_stat;
340 int i;
342 /* Display arbitration + watermarks */
343 PSB_WVDC32(dev_priv->saveDSPARB, DSPARB);
344 PSB_WVDC32(dev_priv->saveDSPFW1, DSPFW1);
345 PSB_WVDC32(dev_priv->saveDSPFW2, DSPFW2);
346 PSB_WVDC32(dev_priv->saveDSPFW3, DSPFW3);
347 PSB_WVDC32(dev_priv->saveDSPFW4, DSPFW4);
348 PSB_WVDC32(dev_priv->saveDSPFW5, DSPFW5);
349 PSB_WVDC32(dev_priv->saveDSPFW6, DSPFW6);
350 PSB_WVDC32(dev_priv->saveCHICKENBIT, DSPCHICKENBIT);
352 /* Make sure VGA plane is off. it initializes to on after reset!*/
353 PSB_WVDC32(0x80000000, VGACNTRL);
355 /* set the plls */
356 PSB_WVDC32(dev_priv->saveFPA0, MRST_FPA0);
357 PSB_WVDC32(dev_priv->saveFPA1, MRST_FPA1);
359 /* Actually enable it */
360 PSB_WVDC32(dev_priv->saveDPLL_A, MRST_DPLL_A);
361 DRM_UDELAY(150);
363 /* Restore mode */
364 PSB_WVDC32(dev_priv->saveHTOTAL_A, HTOTAL_A);
365 PSB_WVDC32(dev_priv->saveHBLANK_A, HBLANK_A);
366 PSB_WVDC32(dev_priv->saveHSYNC_A, HSYNC_A);
367 PSB_WVDC32(dev_priv->saveVTOTAL_A, VTOTAL_A);
368 PSB_WVDC32(dev_priv->saveVBLANK_A, VBLANK_A);
369 PSB_WVDC32(dev_priv->saveVSYNC_A, VSYNC_A);
370 PSB_WVDC32(dev_priv->savePIPEASRC, PIPEASRC);
371 PSB_WVDC32(dev_priv->saveBCLRPAT_A, BCLRPAT_A);
373 /* Restore performance mode*/
374 PSB_WVDC32(dev_priv->savePERF_MODE, MRST_PERF_MODE);
376 /* Enable the pipe*/
377 if (dev_priv->iLVDS_enable)
378 PSB_WVDC32(dev_priv->savePIPEACONF, PIPEACONF);
380 /* Set up the plane*/
381 PSB_WVDC32(dev_priv->saveDSPALINOFF, DSPALINOFF);
382 PSB_WVDC32(dev_priv->saveDSPASTRIDE, DSPASTRIDE);
383 PSB_WVDC32(dev_priv->saveDSPATILEOFF, DSPATILEOFF);
385 /* Enable the plane */
386 PSB_WVDC32(dev_priv->saveDSPACNTR, DSPACNTR);
387 PSB_WVDC32(dev_priv->saveDSPASURF, DSPASURF);
389 /* Enable Cursor A */
390 PSB_WVDC32(dev_priv->saveDSPACURSOR_CTRL, CURACNTR);
391 PSB_WVDC32(dev_priv->saveDSPACURSOR_POS, CURAPOS);
392 PSB_WVDC32(dev_priv->saveDSPACURSOR_BASE, CURABASE);
394 /* Restore palette (gamma) */
395 for (i = 0; i < 256; i++)
396 PSB_WVDC32(dev_priv->save_palette_a[i], PALETTE_A + (i << 2));
398 if (dev_priv->hdmi_priv)
399 mrst_hdmi_restore(dev);
401 if (dev_priv->iLVDS_enable) {
402 PSB_WVDC32(dev_priv->saveBLC_PWM_CTL2, BLC_PWM_CTL2);
403 PSB_WVDC32(dev_priv->saveLVDS, LVDS); /*port 61180h*/
404 PSB_WVDC32(dev_priv->savePFIT_CONTROL, PFIT_CONTROL);
405 PSB_WVDC32(dev_priv->savePFIT_PGM_RATIOS, PFIT_PGM_RATIOS);
406 PSB_WVDC32(dev_priv->savePFIT_AUTO_RATIOS, PFIT_AUTO_RATIOS);
407 PSB_WVDC32(dev_priv->saveBLC_PWM_CTL, BLC_PWM_CTL);
408 PSB_WVDC32(dev_priv->savePP_ON_DELAYS, LVDSPP_ON);
409 PSB_WVDC32(dev_priv->savePP_OFF_DELAYS, LVDSPP_OFF);
410 PSB_WVDC32(dev_priv->savePP_DIVISOR, PP_CYCLE);
411 PSB_WVDC32(dev_priv->savePP_CONTROL, PP_CONTROL);
414 /* Wait for cycle delay */
415 do {
416 pp_stat = PSB_RVDC32(PP_STATUS);
417 } while (pp_stat & 0x08000000);
419 /* Wait for panel power up */
420 do {
421 pp_stat = PSB_RVDC32(PP_STATUS);
422 } while (pp_stat & 0x10000000);
424 /* Restore HW overlay */
425 PSB_WVDC32(dev_priv->saveOV_OVADD, OV_OVADD);
426 PSB_WVDC32(dev_priv->saveOV_OGAMC0, OV_OGAMC0);
427 PSB_WVDC32(dev_priv->saveOV_OGAMC1, OV_OGAMC1);
428 PSB_WVDC32(dev_priv->saveOV_OGAMC2, OV_OGAMC2);
429 PSB_WVDC32(dev_priv->saveOV_OGAMC3, OV_OGAMC3);
430 PSB_WVDC32(dev_priv->saveOV_OGAMC4, OV_OGAMC4);
431 PSB_WVDC32(dev_priv->saveOV_OGAMC5, OV_OGAMC5);
433 /* DPST registers */
434 PSB_WVDC32(dev_priv->saveHISTOGRAM_INT_CONTROL_REG,
435 HISTOGRAM_INT_CONTROL);
436 PSB_WVDC32(dev_priv->saveHISTOGRAM_LOGIC_CONTROL_REG,
437 HISTOGRAM_LOGIC_CONTROL);
438 PSB_WVDC32(dev_priv->savePWM_CONTROL_LOGIC, PWM_CONTROL_LOGIC);
440 return 0;
444 * mrst_power_down - power down the display island
445 * @dev: our DRM device
447 * Power down the display interface of our device
449 static int mrst_power_down(struct drm_device *dev)
451 struct drm_psb_private *dev_priv = dev->dev_private;
452 u32 pwr_mask ;
453 u32 pwr_sts;
455 pwr_mask = PSB_PWRGT_DISPLAY_MASK;
456 outl(pwr_mask, dev_priv->ospm_base + PSB_PM_SSC);
458 while (true) {
459 pwr_sts = inl(dev_priv->ospm_base + PSB_PM_SSS);
460 if ((pwr_sts & pwr_mask) == pwr_mask)
461 break;
462 else
463 udelay(10);
465 return 0;
469 * mrst_power_up
471 * Restore power to the specified island(s) (powergating)
473 static int mrst_power_up(struct drm_device *dev)
475 struct drm_psb_private *dev_priv = dev->dev_private;
476 u32 pwr_mask = PSB_PWRGT_DISPLAY_MASK;
477 u32 pwr_sts, pwr_cnt;
479 pwr_cnt = inl(dev_priv->ospm_base + PSB_PM_SSC);
480 pwr_cnt &= ~pwr_mask;
481 outl(pwr_cnt, (dev_priv->ospm_base + PSB_PM_SSC));
483 while (true) {
484 pwr_sts = inl(dev_priv->ospm_base + PSB_PM_SSS);
485 if ((pwr_sts & pwr_mask) == 0)
486 break;
487 else
488 udelay(10);
490 return 0;
493 #if defined(CONFIG_X86_MRST)
494 static void mrst_lvds_cache_bl(struct drm_device *dev)
496 struct drm_psb_private *dev_priv = dev->dev_private;
498 intel_scu_ipc_ioread8(0x28, &(dev_priv->saveBKLTCNT));
499 intel_scu_ipc_ioread8(0x29, &(dev_priv->saveBKLTREQ));
500 intel_scu_ipc_ioread8(0x2A, &(dev_priv->saveBKLTBRTL));
503 static void mrst_mm_bl_power(struct drm_device *dev, bool on)
505 struct drm_psb_private *dev_priv = dev->dev_private;
507 if (on) {
508 intel_scu_ipc_iowrite8(0x2A, dev_priv->saveBKLTBRTL);
509 intel_scu_ipc_iowrite8(0x28, dev_priv->saveBKLTCNT);
510 intel_scu_ipc_iowrite8(0x29, dev_priv->saveBKLTREQ);
511 } else {
512 intel_scu_ipc_iowrite8(0x2A, 0);
513 intel_scu_ipc_iowrite8(0x28, 0);
514 intel_scu_ipc_iowrite8(0x29, 0);
518 static const struct psb_ops mrst_mm_chip_ops = {
519 .name = "Moorestown MM ",
520 .accel_2d = 1,
521 .pipes = 1,
522 .crtcs = 1,
523 .sgx_offset = MRST_SGX_OFFSET,
525 .crtc_helper = &mrst_helper_funcs,
526 .crtc_funcs = &psb_intel_crtc_funcs,
528 .output_init = mrst_output_init,
530 .lvds_bl_power = mrst_mm_bl_power,
531 #ifdef CONFIG_BACKLIGHT_CLASS_DEVICE
532 .backlight_init = mrst_backlight_init,
533 #endif
535 .init_pm = mrst_init_pm,
536 .save_regs = mrst_save_display_registers,
537 .restore_regs = mrst_restore_display_registers,
538 .power_down = mrst_power_down,
539 .power_up = mrst_power_up,
541 .i2c_bus = 0,
544 #endif
546 static void oaktrail_teardown(struct drm_device *dev)
548 mrst_hdmi_teardown(dev);
551 static const struct psb_ops oaktrail_chip_ops = {
552 .name = "Oaktrail",
553 .accel_2d = 1,
554 .pipes = 2,
555 .crtcs = 2,
556 .sgx_offset = MRST_SGX_OFFSET,
558 .chip_setup = mid_chip_setup,
559 .chip_teardown = oaktrail_teardown,
560 .crtc_helper = &mrst_helper_funcs,
561 .crtc_funcs = &psb_intel_crtc_funcs,
563 .output_init = mrst_output_init,
565 #ifdef CONFIG_BACKLIGHT_CLASS_DEVICE
566 .backlight_init = mrst_backlight_init,
567 #endif
569 .init_pm = mrst_init_pm,
570 .save_regs = mrst_save_display_registers,
571 .restore_regs = mrst_restore_display_registers,
572 .power_down = mrst_power_down,
573 .power_up = mrst_power_up,
575 .i2c_bus = 1,
579 * mrst_chip_setup - perform the initial chip init
580 * @dev: Our drm_device
582 * Figure out which incarnation we are and then scan the firmware for
583 * tables and information.
585 static int mrst_chip_setup(struct drm_device *dev)
587 struct drm_psb_private *dev_priv = dev->dev_private;
589 switch (mrst_device_ident(dev)) {
590 case DEVICE_OAKTRAIL:
591 /* Dual CRTC, PC compatible, HDMI, I2C #2 */
592 dev_priv->ops = &oaktrail_chip_ops;
593 mrst_hdmi_setup(dev);
594 return mid_chip_setup(dev);
595 #if defined(CONFIG_X86_MRST)
596 case DEVICE_MOORESTOWN_MM:
597 /* Single CRTC, No HDMI, I2C #0, BL control */
598 mrst_lvds_cache_bl(dev);
599 dev_priv->ops = &mrst_mm_chip_ops;
600 return mid_chip_setup(dev);
601 case DEVICE_MOORESTOWN:
602 /* Dual CRTC, No HDMI(?), I2C #1 */
603 return mid_chip_setup(dev);
604 #endif
605 default:
606 dev_err(dev->dev, "unsupported device type.\n");
607 return -ENODEV;
611 const struct psb_ops mrst_chip_ops = {
612 .name = "Moorestown",
613 .accel_2d = 1,
614 .pipes = 2,
615 .crtcs = 2,
616 .sgx_offset = MRST_SGX_OFFSET,
618 .chip_setup = mrst_chip_setup,
619 .crtc_helper = &mrst_helper_funcs,
620 .crtc_funcs = &psb_intel_crtc_funcs,
622 .output_init = mrst_output_init,
624 #ifdef CONFIG_BACKLIGHT_CLASS_DEVICE
625 .backlight_init = mrst_backlight_init,
626 #endif
628 .init_pm = mrst_init_pm,
629 .save_regs = mrst_save_display_registers,
630 .restore_regs = mrst_restore_display_registers,
631 .power_down = mrst_power_down,
632 .power_up = mrst_power_up,
634 .i2c_bus = 2,