gma500@ Fix backlight range error
[zen-stable.git] / drivers / staging / gma500 / mrst_device.c
blob6707fafbfa1e2ac0076a14473a7843fa39995855
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 (value > (unsigned long long)MRST_BLC_MAX_PWM_REG_FREQ)
161 return -ERANGE;
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);
168 return 0;
171 static const struct backlight_ops mrst_ops = {
172 .get_brightness = mrst_get_brightness,
173 .update_status = mrst_set_brightness,
176 int mrst_backlight_init(struct drm_device *dev)
178 struct drm_psb_private *dev_priv = dev->dev_private;
179 int ret;
180 struct backlight_properties props;
182 memset(&props, 0, sizeof(struct backlight_properties));
183 props.max_brightness = 100;
184 props.type = BACKLIGHT_PLATFORM;
186 mrst_backlight_device = backlight_device_register("mrst-bl",
187 NULL, (void *)dev, &mrst_ops, &props);
189 if (IS_ERR(mrst_backlight_device))
190 return PTR_ERR(mrst_backlight_device);
192 ret = device_backlight_init(dev);
193 if (ret < 0) {
194 backlight_device_unregister(mrst_backlight_device);
195 return ret;
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;
204 #endif
207 * Provide the Moorestown specific chip logic and low level methods
208 * for power management
211 static void mrst_init_pm(struct drm_device *dev)
216 * mrst_save_display_registers - save registers lost on suspend
217 * @dev: our DRM device
219 * Save the state we need in order to be able to restore the interface
220 * upon resume from suspend
222 static int mrst_save_display_registers(struct drm_device *dev)
224 struct drm_psb_private *dev_priv = dev->dev_private;
225 int i;
226 u32 pp_stat;
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);
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);
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);
263 /* Save palette (gamma) */
264 for (i = 0; i < 256; i++)
265 dev_priv->save_palette_a[i] = PSB_RVDC32(PALETTE_A + (i << 2));
267 if (dev_priv->hdmi_priv)
268 mrst_hdmi_save(dev);
270 /* Save performance state */
271 dev_priv->savePERF_MODE = PSB_RVDC32(MRST_PERF_MODE);
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);
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);
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);
301 if (dev_priv->iLVDS_enable) {
302 /* Shut down the panel */
303 PSB_WVDC32(0, PP_CONTROL);
305 do {
306 pp_stat = PSB_RVDC32(PP_STATUS);
307 } while (pp_stat & 0x80000000);
309 /* Turn off the plane */
310 PSB_WVDC32(0x58000000, DSPACNTR);
311 /* Trigger the plane disable */
312 PSB_WVDC32(0, DSPASURF);
314 /* Wait ~4 ticks */
315 msleep(4);
317 /* Turn off pipe */
318 PSB_WVDC32(0x0, PIPEACONF);
319 /* Wait ~8 ticks */
320 msleep(8);
322 /* Turn off PLLs */
323 PSB_WVDC32(0, MRST_DPLL_A);
325 return 0;
329 * mrst_restore_display_registers - restore lost register state
330 * @dev: our DRM device
332 * Restore register state that was lost during suspend and resume.
334 static int mrst_restore_display_registers(struct drm_device *dev)
336 struct drm_psb_private *dev_priv = dev->dev_private;
337 u32 pp_stat;
338 int i;
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);
350 /* Make sure VGA plane is off. it initializes to on after reset!*/
351 PSB_WVDC32(0x80000000, VGACNTRL);
353 /* set the plls */
354 PSB_WVDC32(dev_priv->saveFPA0, MRST_FPA0);
355 PSB_WVDC32(dev_priv->saveFPA1, MRST_FPA1);
357 /* Actually enable it */
358 PSB_WVDC32(dev_priv->saveDPLL_A, MRST_DPLL_A);
359 DRM_UDELAY(150);
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);
371 /* Restore performance mode*/
372 PSB_WVDC32(dev_priv->savePERF_MODE, MRST_PERF_MODE);
374 /* Enable the pipe*/
375 if (dev_priv->iLVDS_enable)
376 PSB_WVDC32(dev_priv->savePIPEACONF, PIPEACONF);
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);
383 /* Enable the plane */
384 PSB_WVDC32(dev_priv->saveDSPACNTR, DSPACNTR);
385 PSB_WVDC32(dev_priv->saveDSPASURF, DSPASURF);
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);
392 /* Restore palette (gamma) */
393 for (i = 0; i < 256; i++)
394 PSB_WVDC32(dev_priv->save_palette_a[i], PALETTE_A + (i << 2));
396 if (dev_priv->hdmi_priv)
397 mrst_hdmi_restore(dev);
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);
412 /* Wait for cycle delay */
413 do {
414 pp_stat = PSB_RVDC32(PP_STATUS);
415 } while (pp_stat & 0x08000000);
417 /* Wait for panel power up */
418 do {
419 pp_stat = PSB_RVDC32(PP_STATUS);
420 } while (pp_stat & 0x10000000);
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);
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);
438 return 0;
442 * mrst_power_down - power down the display island
443 * @dev: our DRM device
445 * Power down the display interface of our device
447 static int mrst_power_down(struct drm_device *dev)
449 struct drm_psb_private *dev_priv = dev->dev_private;
450 u32 pwr_mask ;
451 u32 pwr_sts;
453 pwr_mask = PSB_PWRGT_DISPLAY_MASK;
454 outl(pwr_mask, dev_priv->ospm_base + PSB_PM_SSC);
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);
463 return 0;
467 * mrst_power_up
469 * Restore power to the specified island(s) (powergating)
471 static int mrst_power_up(struct drm_device *dev)
473 struct drm_psb_private *dev_priv = dev->dev_private;
474 u32 pwr_mask = PSB_PWRGT_DISPLAY_MASK;
475 u32 pwr_sts, pwr_cnt;
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));
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);
488 return 0;
491 #if defined(CONFIG_X86_MRST)
492 static void mrst_lvds_cache_bl(struct drm_device *dev)
494 struct drm_psb_private *dev_priv = dev->dev_private;
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));
501 static void mrst_mm_bl_power(struct drm_device *dev, bool on)
503 struct drm_psb_private *dev_priv = dev->dev_private;
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);
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,
523 .crtc_helper = &mrst_helper_funcs,
524 .crtc_funcs = &psb_intel_crtc_funcs,
526 .output_init = mrst_output_init,
528 .lvds_bl_power = mrst_mm_bl_power,
529 #ifdef CONFIG_BACKLIGHT_CLASS_DEVICE
530 .backlight_init = mrst_backlight_init,
531 #endif
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,
539 .i2c_bus = 0,
542 #endif
544 static void oaktrail_teardown(struct drm_device *dev)
546 mrst_hdmi_teardown(dev);
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,
556 .chip_setup = mid_chip_setup,
557 .chip_teardown = oaktrail_teardown,
558 .crtc_helper = &mrst_helper_funcs,
559 .crtc_funcs = &psb_intel_crtc_funcs,
561 .output_init = mrst_output_init,
563 #ifdef CONFIG_BACKLIGHT_CLASS_DEVICE
564 .backlight_init = mrst_backlight_init,
565 #endif
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,
573 .i2c_bus = 1,
577 * mrst_chip_setup - perform the initial chip init
578 * @dev: Our drm_device
580 * Figure out which incarnation we are and then scan the firmware for
581 * tables and information.
583 static int mrst_chip_setup(struct drm_device *dev)
585 struct drm_psb_private *dev_priv = dev->dev_private;
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;
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,
616 .chip_setup = mrst_chip_setup,
617 .crtc_helper = &mrst_helper_funcs,
618 .crtc_funcs = &psb_intel_crtc_funcs,
620 .output_init = mrst_output_init,
622 #ifdef CONFIG_BACKLIGHT_CLASS_DEVICE
623 .backlight_init = mrst_backlight_init,
624 #endif
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,
632 .i2c_bus = 2,