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>
32 #include "intel_bios.h"
34 static int oaktrail_output_init(struct drm_device
*dev
)
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
);
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
);
47 * Provide the low level interfaces for the Moorestown backlight
50 #ifdef CONFIG_BACKLIGHT_CLASS_DEVICE
52 #define MRST_BLC_MAX_PWM_REG_FREQ 0xFFFF
53 #define BLC_PWM_PRECISION_FACTOR 100 /* 10000000 */
54 #define BLC_PWM_FREQ_CALC_CONSTANT 32
56 #define BLC_ADJUSTMENT_MAX 100
58 static struct backlight_device
*oaktrail_backlight_device
;
59 static int oaktrail_brightness
;
61 static int oaktrail_set_brightness(struct backlight_device
*bd
)
63 struct drm_device
*dev
= bl_get_data(oaktrail_backlight_device
);
64 struct drm_psb_private
*dev_priv
= dev
->dev_private
;
65 int level
= bd
->props
.brightness
;
69 /* Percentage 1-100% being valid */
73 if (gma_power_begin(dev
, 0)) {
74 /* Calculate and set the brightness value */
75 max_pwm_blc
= REG_READ(BLC_PWM_CTL
) >> 16;
76 blc_pwm_ctl
= level
* max_pwm_blc
/ 100;
78 /* Adjust the backlight level with the percent in
81 blc_pwm_ctl
= blc_pwm_ctl
* dev_priv
->blc_adj1
;
82 blc_pwm_ctl
= blc_pwm_ctl
/ 100;
84 /* Adjust the backlight level with the percent in
87 blc_pwm_ctl
= blc_pwm_ctl
* dev_priv
->blc_adj2
;
88 blc_pwm_ctl
= blc_pwm_ctl
/ 100;
90 /* force PWM bit on */
91 REG_WRITE(BLC_PWM_CTL2
, (0x80000000 | REG_READ(BLC_PWM_CTL2
)));
92 REG_WRITE(BLC_PWM_CTL
, (max_pwm_blc
<< 16) | blc_pwm_ctl
);
95 oaktrail_brightness
= level
;
99 static int oaktrail_get_brightness(struct backlight_device
*bd
)
101 /* return locally cached var instead of HW read (due to DPST etc.) */
102 /* FIXME: ideally return actual value in case firmware fiddled with
104 return oaktrail_brightness
;
107 static int device_backlight_init(struct drm_device
*dev
)
109 struct drm_psb_private
*dev_priv
= dev
->dev_private
;
110 unsigned long core_clock
;
113 uint32_t blc_pwm_precision_factor
;
115 dev_priv
->blc_adj1
= BLC_ADJUSTMENT_MAX
;
116 dev_priv
->blc_adj2
= BLC_ADJUSTMENT_MAX
;
118 /* this needs to be set elsewhere */
119 blc_pwm_precision_factor
= BLC_PWM_PRECISION_FACTOR
;
121 core_clock
= dev_priv
->core_freq
;
123 value
= (core_clock
* MHz
) / BLC_PWM_FREQ_CALC_CONSTANT
;
124 value
*= blc_pwm_precision_factor
;
125 value
/= bl_max_freq
;
126 value
/= blc_pwm_precision_factor
;
128 if (value
> (unsigned long long)MRST_BLC_MAX_PWM_REG_FREQ
)
131 if (gma_power_begin(dev
, false)) {
132 REG_WRITE(BLC_PWM_CTL2
, (0x80000000 | REG_READ(BLC_PWM_CTL2
)));
133 REG_WRITE(BLC_PWM_CTL
, value
| (value
<< 16));
139 static const struct backlight_ops oaktrail_ops
= {
140 .get_brightness
= oaktrail_get_brightness
,
141 .update_status
= oaktrail_set_brightness
,
144 int oaktrail_backlight_init(struct drm_device
*dev
)
146 struct drm_psb_private
*dev_priv
= dev
->dev_private
;
148 struct backlight_properties props
;
150 memset(&props
, 0, sizeof(struct backlight_properties
));
151 props
.max_brightness
= 100;
152 props
.type
= BACKLIGHT_PLATFORM
;
154 oaktrail_backlight_device
= backlight_device_register("oaktrail-bl",
155 NULL
, (void *)dev
, &oaktrail_ops
, &props
);
157 if (IS_ERR(oaktrail_backlight_device
))
158 return PTR_ERR(oaktrail_backlight_device
);
160 ret
= device_backlight_init(dev
);
162 backlight_device_unregister(oaktrail_backlight_device
);
165 oaktrail_backlight_device
->props
.brightness
= 100;
166 oaktrail_backlight_device
->props
.max_brightness
= 100;
167 backlight_update_status(oaktrail_backlight_device
);
168 dev_priv
->backlight_device
= oaktrail_backlight_device
;
175 * Provide the Moorestown specific chip logic and low level methods
176 * for power management
179 static void oaktrail_init_pm(struct drm_device
*dev
)
184 * oaktrail_save_display_registers - save registers lost on suspend
185 * @dev: our DRM device
187 * Save the state we need in order to be able to restore the interface
188 * upon resume from suspend
190 static int oaktrail_save_display_registers(struct drm_device
*dev
)
192 struct drm_psb_private
*dev_priv
= dev
->dev_private
;
196 /* Display arbitration control + watermarks */
197 dev_priv
->saveDSPARB
= PSB_RVDC32(DSPARB
);
198 dev_priv
->saveDSPFW1
= PSB_RVDC32(DSPFW1
);
199 dev_priv
->saveDSPFW2
= PSB_RVDC32(DSPFW2
);
200 dev_priv
->saveDSPFW3
= PSB_RVDC32(DSPFW3
);
201 dev_priv
->saveDSPFW4
= PSB_RVDC32(DSPFW4
);
202 dev_priv
->saveDSPFW5
= PSB_RVDC32(DSPFW5
);
203 dev_priv
->saveDSPFW6
= PSB_RVDC32(DSPFW6
);
204 dev_priv
->saveCHICKENBIT
= PSB_RVDC32(DSPCHICKENBIT
);
206 /* Pipe & plane A info */
207 dev_priv
->savePIPEACONF
= PSB_RVDC32(PIPEACONF
);
208 dev_priv
->savePIPEASRC
= PSB_RVDC32(PIPEASRC
);
209 dev_priv
->saveFPA0
= PSB_RVDC32(MRST_FPA0
);
210 dev_priv
->saveFPA1
= PSB_RVDC32(MRST_FPA1
);
211 dev_priv
->saveDPLL_A
= PSB_RVDC32(MRST_DPLL_A
);
212 dev_priv
->saveHTOTAL_A
= PSB_RVDC32(HTOTAL_A
);
213 dev_priv
->saveHBLANK_A
= PSB_RVDC32(HBLANK_A
);
214 dev_priv
->saveHSYNC_A
= PSB_RVDC32(HSYNC_A
);
215 dev_priv
->saveVTOTAL_A
= PSB_RVDC32(VTOTAL_A
);
216 dev_priv
->saveVBLANK_A
= PSB_RVDC32(VBLANK_A
);
217 dev_priv
->saveVSYNC_A
= PSB_RVDC32(VSYNC_A
);
218 dev_priv
->saveBCLRPAT_A
= PSB_RVDC32(BCLRPAT_A
);
219 dev_priv
->saveDSPACNTR
= PSB_RVDC32(DSPACNTR
);
220 dev_priv
->saveDSPASTRIDE
= PSB_RVDC32(DSPASTRIDE
);
221 dev_priv
->saveDSPAADDR
= PSB_RVDC32(DSPABASE
);
222 dev_priv
->saveDSPASURF
= PSB_RVDC32(DSPASURF
);
223 dev_priv
->saveDSPALINOFF
= PSB_RVDC32(DSPALINOFF
);
224 dev_priv
->saveDSPATILEOFF
= PSB_RVDC32(DSPATILEOFF
);
226 /* Save cursor regs */
227 dev_priv
->saveDSPACURSOR_CTRL
= PSB_RVDC32(CURACNTR
);
228 dev_priv
->saveDSPACURSOR_BASE
= PSB_RVDC32(CURABASE
);
229 dev_priv
->saveDSPACURSOR_POS
= PSB_RVDC32(CURAPOS
);
231 /* Save palette (gamma) */
232 for (i
= 0; i
< 256; i
++)
233 dev_priv
->save_palette_a
[i
] = PSB_RVDC32(PALETTE_A
+ (i
<< 2));
235 if (dev_priv
->hdmi_priv
)
236 oaktrail_hdmi_save(dev
);
238 /* Save performance state */
239 dev_priv
->savePERF_MODE
= PSB_RVDC32(MRST_PERF_MODE
);
242 dev_priv
->savePP_CONTROL
= PSB_RVDC32(PP_CONTROL
);
243 dev_priv
->savePFIT_PGM_RATIOS
= PSB_RVDC32(PFIT_PGM_RATIOS
);
244 dev_priv
->savePFIT_AUTO_RATIOS
= PSB_RVDC32(PFIT_AUTO_RATIOS
);
245 dev_priv
->saveBLC_PWM_CTL
= PSB_RVDC32(BLC_PWM_CTL
);
246 dev_priv
->saveBLC_PWM_CTL2
= PSB_RVDC32(BLC_PWM_CTL2
);
247 dev_priv
->saveLVDS
= PSB_RVDC32(LVDS
);
248 dev_priv
->savePFIT_CONTROL
= PSB_RVDC32(PFIT_CONTROL
);
249 dev_priv
->savePP_ON_DELAYS
= PSB_RVDC32(LVDSPP_ON
);
250 dev_priv
->savePP_OFF_DELAYS
= PSB_RVDC32(LVDSPP_OFF
);
251 dev_priv
->savePP_DIVISOR
= PSB_RVDC32(PP_CYCLE
);
254 dev_priv
->saveOV_OVADD
= PSB_RVDC32(OV_OVADD
);
255 dev_priv
->saveOV_OGAMC0
= PSB_RVDC32(OV_OGAMC0
);
256 dev_priv
->saveOV_OGAMC1
= PSB_RVDC32(OV_OGAMC1
);
257 dev_priv
->saveOV_OGAMC2
= PSB_RVDC32(OV_OGAMC2
);
258 dev_priv
->saveOV_OGAMC3
= PSB_RVDC32(OV_OGAMC3
);
259 dev_priv
->saveOV_OGAMC4
= PSB_RVDC32(OV_OGAMC4
);
260 dev_priv
->saveOV_OGAMC5
= PSB_RVDC32(OV_OGAMC5
);
263 dev_priv
->saveHISTOGRAM_INT_CONTROL_REG
=
264 PSB_RVDC32(HISTOGRAM_INT_CONTROL
);
265 dev_priv
->saveHISTOGRAM_LOGIC_CONTROL_REG
=
266 PSB_RVDC32(HISTOGRAM_LOGIC_CONTROL
);
267 dev_priv
->savePWM_CONTROL_LOGIC
= PSB_RVDC32(PWM_CONTROL_LOGIC
);
269 if (dev_priv
->iLVDS_enable
) {
270 /* Shut down the panel */
271 PSB_WVDC32(0, PP_CONTROL
);
274 pp_stat
= PSB_RVDC32(PP_STATUS
);
275 } while (pp_stat
& 0x80000000);
277 /* Turn off the plane */
278 PSB_WVDC32(0x58000000, DSPACNTR
);
279 /* Trigger the plane disable */
280 PSB_WVDC32(0, DSPASURF
);
286 PSB_WVDC32(0x0, PIPEACONF
);
291 PSB_WVDC32(0, MRST_DPLL_A
);
297 * oaktrail_restore_display_registers - restore lost register state
298 * @dev: our DRM device
300 * Restore register state that was lost during suspend and resume.
302 static int oaktrail_restore_display_registers(struct drm_device
*dev
)
304 struct drm_psb_private
*dev_priv
= dev
->dev_private
;
308 /* Display arbitration + watermarks */
309 PSB_WVDC32(dev_priv
->saveDSPARB
, DSPARB
);
310 PSB_WVDC32(dev_priv
->saveDSPFW1
, DSPFW1
);
311 PSB_WVDC32(dev_priv
->saveDSPFW2
, DSPFW2
);
312 PSB_WVDC32(dev_priv
->saveDSPFW3
, DSPFW3
);
313 PSB_WVDC32(dev_priv
->saveDSPFW4
, DSPFW4
);
314 PSB_WVDC32(dev_priv
->saveDSPFW5
, DSPFW5
);
315 PSB_WVDC32(dev_priv
->saveDSPFW6
, DSPFW6
);
316 PSB_WVDC32(dev_priv
->saveCHICKENBIT
, DSPCHICKENBIT
);
318 /* Make sure VGA plane is off. it initializes to on after reset!*/
319 PSB_WVDC32(0x80000000, VGACNTRL
);
322 PSB_WVDC32(dev_priv
->saveFPA0
, MRST_FPA0
);
323 PSB_WVDC32(dev_priv
->saveFPA1
, MRST_FPA1
);
325 /* Actually enable it */
326 PSB_WVDC32(dev_priv
->saveDPLL_A
, MRST_DPLL_A
);
330 PSB_WVDC32(dev_priv
->saveHTOTAL_A
, HTOTAL_A
);
331 PSB_WVDC32(dev_priv
->saveHBLANK_A
, HBLANK_A
);
332 PSB_WVDC32(dev_priv
->saveHSYNC_A
, HSYNC_A
);
333 PSB_WVDC32(dev_priv
->saveVTOTAL_A
, VTOTAL_A
);
334 PSB_WVDC32(dev_priv
->saveVBLANK_A
, VBLANK_A
);
335 PSB_WVDC32(dev_priv
->saveVSYNC_A
, VSYNC_A
);
336 PSB_WVDC32(dev_priv
->savePIPEASRC
, PIPEASRC
);
337 PSB_WVDC32(dev_priv
->saveBCLRPAT_A
, BCLRPAT_A
);
339 /* Restore performance mode*/
340 PSB_WVDC32(dev_priv
->savePERF_MODE
, MRST_PERF_MODE
);
343 if (dev_priv
->iLVDS_enable
)
344 PSB_WVDC32(dev_priv
->savePIPEACONF
, PIPEACONF
);
346 /* Set up the plane*/
347 PSB_WVDC32(dev_priv
->saveDSPALINOFF
, DSPALINOFF
);
348 PSB_WVDC32(dev_priv
->saveDSPASTRIDE
, DSPASTRIDE
);
349 PSB_WVDC32(dev_priv
->saveDSPATILEOFF
, DSPATILEOFF
);
351 /* Enable the plane */
352 PSB_WVDC32(dev_priv
->saveDSPACNTR
, DSPACNTR
);
353 PSB_WVDC32(dev_priv
->saveDSPASURF
, DSPASURF
);
355 /* Enable Cursor A */
356 PSB_WVDC32(dev_priv
->saveDSPACURSOR_CTRL
, CURACNTR
);
357 PSB_WVDC32(dev_priv
->saveDSPACURSOR_POS
, CURAPOS
);
358 PSB_WVDC32(dev_priv
->saveDSPACURSOR_BASE
, CURABASE
);
360 /* Restore palette (gamma) */
361 for (i
= 0; i
< 256; i
++)
362 PSB_WVDC32(dev_priv
->save_palette_a
[i
], PALETTE_A
+ (i
<< 2));
364 if (dev_priv
->hdmi_priv
)
365 oaktrail_hdmi_restore(dev
);
367 if (dev_priv
->iLVDS_enable
) {
368 PSB_WVDC32(dev_priv
->saveBLC_PWM_CTL2
, BLC_PWM_CTL2
);
369 PSB_WVDC32(dev_priv
->saveLVDS
, LVDS
); /*port 61180h*/
370 PSB_WVDC32(dev_priv
->savePFIT_CONTROL
, PFIT_CONTROL
);
371 PSB_WVDC32(dev_priv
->savePFIT_PGM_RATIOS
, PFIT_PGM_RATIOS
);
372 PSB_WVDC32(dev_priv
->savePFIT_AUTO_RATIOS
, PFIT_AUTO_RATIOS
);
373 PSB_WVDC32(dev_priv
->saveBLC_PWM_CTL
, BLC_PWM_CTL
);
374 PSB_WVDC32(dev_priv
->savePP_ON_DELAYS
, LVDSPP_ON
);
375 PSB_WVDC32(dev_priv
->savePP_OFF_DELAYS
, LVDSPP_OFF
);
376 PSB_WVDC32(dev_priv
->savePP_DIVISOR
, PP_CYCLE
);
377 PSB_WVDC32(dev_priv
->savePP_CONTROL
, PP_CONTROL
);
380 /* Wait for cycle delay */
382 pp_stat
= PSB_RVDC32(PP_STATUS
);
383 } while (pp_stat
& 0x08000000);
385 /* Wait for panel power up */
387 pp_stat
= PSB_RVDC32(PP_STATUS
);
388 } while (pp_stat
& 0x10000000);
390 /* Restore HW overlay */
391 PSB_WVDC32(dev_priv
->saveOV_OVADD
, OV_OVADD
);
392 PSB_WVDC32(dev_priv
->saveOV_OGAMC0
, OV_OGAMC0
);
393 PSB_WVDC32(dev_priv
->saveOV_OGAMC1
, OV_OGAMC1
);
394 PSB_WVDC32(dev_priv
->saveOV_OGAMC2
, OV_OGAMC2
);
395 PSB_WVDC32(dev_priv
->saveOV_OGAMC3
, OV_OGAMC3
);
396 PSB_WVDC32(dev_priv
->saveOV_OGAMC4
, OV_OGAMC4
);
397 PSB_WVDC32(dev_priv
->saveOV_OGAMC5
, OV_OGAMC5
);
400 PSB_WVDC32(dev_priv
->saveHISTOGRAM_INT_CONTROL_REG
,
401 HISTOGRAM_INT_CONTROL
);
402 PSB_WVDC32(dev_priv
->saveHISTOGRAM_LOGIC_CONTROL_REG
,
403 HISTOGRAM_LOGIC_CONTROL
);
404 PSB_WVDC32(dev_priv
->savePWM_CONTROL_LOGIC
, PWM_CONTROL_LOGIC
);
410 * oaktrail_power_down - power down the display island
411 * @dev: our DRM device
413 * Power down the display interface of our device
415 static int oaktrail_power_down(struct drm_device
*dev
)
417 struct drm_psb_private
*dev_priv
= dev
->dev_private
;
421 pwr_mask
= PSB_PWRGT_DISPLAY_MASK
;
422 outl(pwr_mask
, dev_priv
->ospm_base
+ PSB_PM_SSC
);
425 pwr_sts
= inl(dev_priv
->ospm_base
+ PSB_PM_SSS
);
426 if ((pwr_sts
& pwr_mask
) == pwr_mask
)
437 * Restore power to the specified island(s) (powergating)
439 static int oaktrail_power_up(struct drm_device
*dev
)
441 struct drm_psb_private
*dev_priv
= dev
->dev_private
;
442 u32 pwr_mask
= PSB_PWRGT_DISPLAY_MASK
;
443 u32 pwr_sts
, pwr_cnt
;
445 pwr_cnt
= inl(dev_priv
->ospm_base
+ PSB_PM_SSC
);
446 pwr_cnt
&= ~pwr_mask
;
447 outl(pwr_cnt
, (dev_priv
->ospm_base
+ PSB_PM_SSC
));
450 pwr_sts
= inl(dev_priv
->ospm_base
+ PSB_PM_SSS
);
451 if ((pwr_sts
& pwr_mask
) == 0)
460 static int oaktrail_chip_setup(struct drm_device
*dev
)
462 struct drm_psb_private
*dev_priv
= dev
->dev_private
;
463 struct oaktrail_vbt
*vbt
= &dev_priv
->vbt_data
;
466 ret
= mid_chip_setup(dev
);
469 if (vbt
->size
== 0) {
470 /* Now pull the BIOS data */
471 gma_intel_opregion_init(dev
);
472 psb_intel_init_bios(dev
);
477 static void oaktrail_teardown(struct drm_device
*dev
)
479 struct drm_psb_private
*dev_priv
= dev
->dev_private
;
480 struct oaktrail_vbt
*vbt
= &dev_priv
->vbt_data
;
482 oaktrail_hdmi_teardown(dev
);
484 psb_intel_destroy_bios(dev
);
487 const struct psb_ops oaktrail_chip_ops
= {
492 .sgx_offset
= MRST_SGX_OFFSET
,
494 .chip_setup
= oaktrail_chip_setup
,
495 .chip_teardown
= oaktrail_teardown
,
496 .crtc_helper
= &oaktrail_helper_funcs
,
497 .crtc_funcs
= &psb_intel_crtc_funcs
,
499 .output_init
= oaktrail_output_init
,
501 #ifdef CONFIG_BACKLIGHT_CLASS_DEVICE
502 .backlight_init
= oaktrail_backlight_init
,
505 .init_pm
= oaktrail_init_pm
,
506 .save_regs
= oaktrail_save_display_registers
,
507 .restore_regs
= oaktrail_restore_display_registers
,
508 .power_down
= oaktrail_power_down
,
509 .power_up
= oaktrail_power_up
,