1 /**************************************************************************
2 * Copyright (c) 2011, Intel Corporation.
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
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>
28 #include "psb_intel_reg.h"
30 #include <asm/intel_scu_ipc.h>
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
)
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
;
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
);
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
);
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
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
;
101 /* Percentage 1-100% being valid */
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
);
127 mrst_brightness
= level
;
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
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
;
145 uint32_t blc_pwm_precision_factor
;
147 dev_priv
->blc_adj1
= BLC_ADJUSTMENT_MAX
;
148 dev_priv
->blc_adj2
= BLC_ADJUSTMENT_MAX
;
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
)
164 REG_WRITE(BLC_PWM_CTL2
,
165 (0x80000000 | REG_READ(BLC_PWM_CTL2
)));
166 REG_WRITE(BLC_PWM_CTL
, value
| (value
<< 16));
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
;
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
);
196 backlight_device_unregister(mrst_backlight_device
);
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
;
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
;
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
)
272 /* Save performance state */
273 dev_priv
->savePERF_MODE
= PSB_RVDC32(MRST_PERF_MODE
);
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
);
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
);
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
);
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
);
320 PSB_WVDC32(0x0, PIPEACONF
);
325 PSB_WVDC32(0, MRST_DPLL_A
);
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
;
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
);
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
);
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
);
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 */
416 pp_stat
= PSB_RVDC32(PP_STATUS
);
417 } while (pp_stat
& 0x08000000);
419 /* Wait for panel power up */
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
);
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
);
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
;
455 pwr_mask
= PSB_PWRGT_DISPLAY_MASK
;
456 outl(pwr_mask
, dev_priv
->ospm_base
+ PSB_PM_SSC
);
459 pwr_sts
= inl(dev_priv
->ospm_base
+ PSB_PM_SSS
);
460 if ((pwr_sts
& pwr_mask
) == pwr_mask
)
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
));
484 pwr_sts
= inl(dev_priv
->ospm_base
+ PSB_PM_SSS
);
485 if ((pwr_sts
& pwr_mask
) == 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
;
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
);
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 ",
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
,
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
,
546 static void oaktrail_teardown(struct drm_device
*dev
)
548 mrst_hdmi_teardown(dev
);
551 static const struct psb_ops oaktrail_chip_ops
= {
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
,
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
,
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
);
606 dev_err(dev
->dev
, "unsupported device type.\n");
611 const struct psb_ops mrst_chip_ops
= {
612 .name
= "Moorestown",
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
,
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
,