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 static 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
180 * oaktrail_save_display_registers - save registers lost on suspend
181 * @dev: our DRM device
183 * Save the state we need in order to be able to restore the interface
184 * upon resume from suspend
186 static int oaktrail_save_display_registers(struct drm_device
*dev
)
188 struct drm_psb_private
*dev_priv
= dev
->dev_private
;
189 struct psb_save_area
*regs
= &dev_priv
->regs
;
193 /* Display arbitration control + watermarks */
194 regs
->psb
.saveDSPARB
= PSB_RVDC32(DSPARB
);
195 regs
->psb
.saveDSPFW1
= PSB_RVDC32(DSPFW1
);
196 regs
->psb
.saveDSPFW2
= PSB_RVDC32(DSPFW2
);
197 regs
->psb
.saveDSPFW3
= PSB_RVDC32(DSPFW3
);
198 regs
->psb
.saveDSPFW4
= PSB_RVDC32(DSPFW4
);
199 regs
->psb
.saveDSPFW5
= PSB_RVDC32(DSPFW5
);
200 regs
->psb
.saveDSPFW6
= PSB_RVDC32(DSPFW6
);
201 regs
->psb
.saveCHICKENBIT
= PSB_RVDC32(DSPCHICKENBIT
);
203 /* Pipe & plane A info */
204 regs
->psb
.savePIPEACONF
= PSB_RVDC32(PIPEACONF
);
205 regs
->psb
.savePIPEASRC
= PSB_RVDC32(PIPEASRC
);
206 regs
->psb
.saveFPA0
= PSB_RVDC32(MRST_FPA0
);
207 regs
->psb
.saveFPA1
= PSB_RVDC32(MRST_FPA1
);
208 regs
->psb
.saveDPLL_A
= PSB_RVDC32(MRST_DPLL_A
);
209 regs
->psb
.saveHTOTAL_A
= PSB_RVDC32(HTOTAL_A
);
210 regs
->psb
.saveHBLANK_A
= PSB_RVDC32(HBLANK_A
);
211 regs
->psb
.saveHSYNC_A
= PSB_RVDC32(HSYNC_A
);
212 regs
->psb
.saveVTOTAL_A
= PSB_RVDC32(VTOTAL_A
);
213 regs
->psb
.saveVBLANK_A
= PSB_RVDC32(VBLANK_A
);
214 regs
->psb
.saveVSYNC_A
= PSB_RVDC32(VSYNC_A
);
215 regs
->psb
.saveBCLRPAT_A
= PSB_RVDC32(BCLRPAT_A
);
216 regs
->psb
.saveDSPACNTR
= PSB_RVDC32(DSPACNTR
);
217 regs
->psb
.saveDSPASTRIDE
= PSB_RVDC32(DSPASTRIDE
);
218 regs
->psb
.saveDSPAADDR
= PSB_RVDC32(DSPABASE
);
219 regs
->psb
.saveDSPASURF
= PSB_RVDC32(DSPASURF
);
220 regs
->psb
.saveDSPALINOFF
= PSB_RVDC32(DSPALINOFF
);
221 regs
->psb
.saveDSPATILEOFF
= PSB_RVDC32(DSPATILEOFF
);
223 /* Save cursor regs */
224 regs
->psb
.saveDSPACURSOR_CTRL
= PSB_RVDC32(CURACNTR
);
225 regs
->psb
.saveDSPACURSOR_BASE
= PSB_RVDC32(CURABASE
);
226 regs
->psb
.saveDSPACURSOR_POS
= PSB_RVDC32(CURAPOS
);
228 /* Save palette (gamma) */
229 for (i
= 0; i
< 256; i
++)
230 regs
->psb
.save_palette_a
[i
] = PSB_RVDC32(PALETTE_A
+ (i
<< 2));
232 if (dev_priv
->hdmi_priv
)
233 oaktrail_hdmi_save(dev
);
235 /* Save performance state */
236 regs
->psb
.savePERF_MODE
= PSB_RVDC32(MRST_PERF_MODE
);
239 regs
->psb
.savePP_CONTROL
= PSB_RVDC32(PP_CONTROL
);
240 regs
->psb
.savePFIT_PGM_RATIOS
= PSB_RVDC32(PFIT_PGM_RATIOS
);
241 regs
->psb
.savePFIT_AUTO_RATIOS
= PSB_RVDC32(PFIT_AUTO_RATIOS
);
242 regs
->saveBLC_PWM_CTL
= PSB_RVDC32(BLC_PWM_CTL
);
243 regs
->saveBLC_PWM_CTL2
= PSB_RVDC32(BLC_PWM_CTL2
);
244 regs
->psb
.saveLVDS
= PSB_RVDC32(LVDS
);
245 regs
->psb
.savePFIT_CONTROL
= PSB_RVDC32(PFIT_CONTROL
);
246 regs
->psb
.savePP_ON_DELAYS
= PSB_RVDC32(LVDSPP_ON
);
247 regs
->psb
.savePP_OFF_DELAYS
= PSB_RVDC32(LVDSPP_OFF
);
248 regs
->psb
.savePP_DIVISOR
= PSB_RVDC32(PP_CYCLE
);
251 regs
->psb
.saveOV_OVADD
= PSB_RVDC32(OV_OVADD
);
252 regs
->psb
.saveOV_OGAMC0
= PSB_RVDC32(OV_OGAMC0
);
253 regs
->psb
.saveOV_OGAMC1
= PSB_RVDC32(OV_OGAMC1
);
254 regs
->psb
.saveOV_OGAMC2
= PSB_RVDC32(OV_OGAMC2
);
255 regs
->psb
.saveOV_OGAMC3
= PSB_RVDC32(OV_OGAMC3
);
256 regs
->psb
.saveOV_OGAMC4
= PSB_RVDC32(OV_OGAMC4
);
257 regs
->psb
.saveOV_OGAMC5
= PSB_RVDC32(OV_OGAMC5
);
260 regs
->psb
.saveHISTOGRAM_INT_CONTROL_REG
=
261 PSB_RVDC32(HISTOGRAM_INT_CONTROL
);
262 regs
->psb
.saveHISTOGRAM_LOGIC_CONTROL_REG
=
263 PSB_RVDC32(HISTOGRAM_LOGIC_CONTROL
);
264 regs
->psb
.savePWM_CONTROL_LOGIC
= PSB_RVDC32(PWM_CONTROL_LOGIC
);
266 if (dev_priv
->iLVDS_enable
) {
267 /* Shut down the panel */
268 PSB_WVDC32(0, PP_CONTROL
);
271 pp_stat
= PSB_RVDC32(PP_STATUS
);
272 } while (pp_stat
& 0x80000000);
274 /* Turn off the plane */
275 PSB_WVDC32(0x58000000, DSPACNTR
);
276 /* Trigger the plane disable */
277 PSB_WVDC32(0, DSPASURF
);
283 PSB_WVDC32(0x0, PIPEACONF
);
288 PSB_WVDC32(0, MRST_DPLL_A
);
294 * oaktrail_restore_display_registers - restore lost register state
295 * @dev: our DRM device
297 * Restore register state that was lost during suspend and resume.
299 static int oaktrail_restore_display_registers(struct drm_device
*dev
)
301 struct drm_psb_private
*dev_priv
= dev
->dev_private
;
302 struct psb_save_area
*regs
= &dev_priv
->regs
;
306 /* Display arbitration + watermarks */
307 PSB_WVDC32(regs
->psb
.saveDSPARB
, DSPARB
);
308 PSB_WVDC32(regs
->psb
.saveDSPFW1
, DSPFW1
);
309 PSB_WVDC32(regs
->psb
.saveDSPFW2
, DSPFW2
);
310 PSB_WVDC32(regs
->psb
.saveDSPFW3
, DSPFW3
);
311 PSB_WVDC32(regs
->psb
.saveDSPFW4
, DSPFW4
);
312 PSB_WVDC32(regs
->psb
.saveDSPFW5
, DSPFW5
);
313 PSB_WVDC32(regs
->psb
.saveDSPFW6
, DSPFW6
);
314 PSB_WVDC32(regs
->psb
.saveCHICKENBIT
, DSPCHICKENBIT
);
316 /* Make sure VGA plane is off. it initializes to on after reset!*/
317 PSB_WVDC32(0x80000000, VGACNTRL
);
320 PSB_WVDC32(regs
->psb
.saveFPA0
, MRST_FPA0
);
321 PSB_WVDC32(regs
->psb
.saveFPA1
, MRST_FPA1
);
323 /* Actually enable it */
324 PSB_WVDC32(regs
->psb
.saveDPLL_A
, MRST_DPLL_A
);
328 PSB_WVDC32(regs
->psb
.saveHTOTAL_A
, HTOTAL_A
);
329 PSB_WVDC32(regs
->psb
.saveHBLANK_A
, HBLANK_A
);
330 PSB_WVDC32(regs
->psb
.saveHSYNC_A
, HSYNC_A
);
331 PSB_WVDC32(regs
->psb
.saveVTOTAL_A
, VTOTAL_A
);
332 PSB_WVDC32(regs
->psb
.saveVBLANK_A
, VBLANK_A
);
333 PSB_WVDC32(regs
->psb
.saveVSYNC_A
, VSYNC_A
);
334 PSB_WVDC32(regs
->psb
.savePIPEASRC
, PIPEASRC
);
335 PSB_WVDC32(regs
->psb
.saveBCLRPAT_A
, BCLRPAT_A
);
337 /* Restore performance mode*/
338 PSB_WVDC32(regs
->psb
.savePERF_MODE
, MRST_PERF_MODE
);
341 if (dev_priv
->iLVDS_enable
)
342 PSB_WVDC32(regs
->psb
.savePIPEACONF
, PIPEACONF
);
344 /* Set up the plane*/
345 PSB_WVDC32(regs
->psb
.saveDSPALINOFF
, DSPALINOFF
);
346 PSB_WVDC32(regs
->psb
.saveDSPASTRIDE
, DSPASTRIDE
);
347 PSB_WVDC32(regs
->psb
.saveDSPATILEOFF
, DSPATILEOFF
);
349 /* Enable the plane */
350 PSB_WVDC32(regs
->psb
.saveDSPACNTR
, DSPACNTR
);
351 PSB_WVDC32(regs
->psb
.saveDSPASURF
, DSPASURF
);
353 /* Enable Cursor A */
354 PSB_WVDC32(regs
->psb
.saveDSPACURSOR_CTRL
, CURACNTR
);
355 PSB_WVDC32(regs
->psb
.saveDSPACURSOR_POS
, CURAPOS
);
356 PSB_WVDC32(regs
->psb
.saveDSPACURSOR_BASE
, CURABASE
);
358 /* Restore palette (gamma) */
359 for (i
= 0; i
< 256; i
++)
360 PSB_WVDC32(regs
->psb
.save_palette_a
[i
], PALETTE_A
+ (i
<< 2));
362 if (dev_priv
->hdmi_priv
)
363 oaktrail_hdmi_restore(dev
);
365 if (dev_priv
->iLVDS_enable
) {
366 PSB_WVDC32(regs
->saveBLC_PWM_CTL2
, BLC_PWM_CTL2
);
367 PSB_WVDC32(regs
->psb
.saveLVDS
, LVDS
); /*port 61180h*/
368 PSB_WVDC32(regs
->psb
.savePFIT_CONTROL
, PFIT_CONTROL
);
369 PSB_WVDC32(regs
->psb
.savePFIT_PGM_RATIOS
, PFIT_PGM_RATIOS
);
370 PSB_WVDC32(regs
->psb
.savePFIT_AUTO_RATIOS
, PFIT_AUTO_RATIOS
);
371 PSB_WVDC32(regs
->saveBLC_PWM_CTL
, BLC_PWM_CTL
);
372 PSB_WVDC32(regs
->psb
.savePP_ON_DELAYS
, LVDSPP_ON
);
373 PSB_WVDC32(regs
->psb
.savePP_OFF_DELAYS
, LVDSPP_OFF
);
374 PSB_WVDC32(regs
->psb
.savePP_DIVISOR
, PP_CYCLE
);
375 PSB_WVDC32(regs
->psb
.savePP_CONTROL
, PP_CONTROL
);
378 /* Wait for cycle delay */
380 pp_stat
= PSB_RVDC32(PP_STATUS
);
381 } while (pp_stat
& 0x08000000);
383 /* Wait for panel power up */
385 pp_stat
= PSB_RVDC32(PP_STATUS
);
386 } while (pp_stat
& 0x10000000);
388 /* Restore HW overlay */
389 PSB_WVDC32(regs
->psb
.saveOV_OVADD
, OV_OVADD
);
390 PSB_WVDC32(regs
->psb
.saveOV_OGAMC0
, OV_OGAMC0
);
391 PSB_WVDC32(regs
->psb
.saveOV_OGAMC1
, OV_OGAMC1
);
392 PSB_WVDC32(regs
->psb
.saveOV_OGAMC2
, OV_OGAMC2
);
393 PSB_WVDC32(regs
->psb
.saveOV_OGAMC3
, OV_OGAMC3
);
394 PSB_WVDC32(regs
->psb
.saveOV_OGAMC4
, OV_OGAMC4
);
395 PSB_WVDC32(regs
->psb
.saveOV_OGAMC5
, OV_OGAMC5
);
398 PSB_WVDC32(regs
->psb
.saveHISTOGRAM_INT_CONTROL_REG
,
399 HISTOGRAM_INT_CONTROL
);
400 PSB_WVDC32(regs
->psb
.saveHISTOGRAM_LOGIC_CONTROL_REG
,
401 HISTOGRAM_LOGIC_CONTROL
);
402 PSB_WVDC32(regs
->psb
.savePWM_CONTROL_LOGIC
, PWM_CONTROL_LOGIC
);
408 * oaktrail_power_down - power down the display island
409 * @dev: our DRM device
411 * Power down the display interface of our device
413 static int oaktrail_power_down(struct drm_device
*dev
)
415 struct drm_psb_private
*dev_priv
= dev
->dev_private
;
419 pwr_mask
= PSB_PWRGT_DISPLAY_MASK
;
420 outl(pwr_mask
, dev_priv
->ospm_base
+ PSB_PM_SSC
);
423 pwr_sts
= inl(dev_priv
->ospm_base
+ PSB_PM_SSS
);
424 if ((pwr_sts
& pwr_mask
) == pwr_mask
)
435 * Restore power to the specified island(s) (powergating)
437 static int oaktrail_power_up(struct drm_device
*dev
)
439 struct drm_psb_private
*dev_priv
= dev
->dev_private
;
440 u32 pwr_mask
= PSB_PWRGT_DISPLAY_MASK
;
441 u32 pwr_sts
, pwr_cnt
;
443 pwr_cnt
= inl(dev_priv
->ospm_base
+ PSB_PM_SSC
);
444 pwr_cnt
&= ~pwr_mask
;
445 outl(pwr_cnt
, (dev_priv
->ospm_base
+ PSB_PM_SSC
));
448 pwr_sts
= inl(dev_priv
->ospm_base
+ PSB_PM_SSS
);
449 if ((pwr_sts
& pwr_mask
) == 0)
458 static int oaktrail_chip_setup(struct drm_device
*dev
)
460 struct drm_psb_private
*dev_priv
= dev
->dev_private
;
463 ret
= mid_chip_setup(dev
);
466 if (!dev_priv
->has_gct
) {
467 /* Now pull the BIOS data */
468 psb_intel_opregion_init(dev
);
469 psb_intel_init_bios(dev
);
471 oaktrail_hdmi_setup(dev
);
475 static void oaktrail_teardown(struct drm_device
*dev
)
477 struct drm_psb_private
*dev_priv
= dev
->dev_private
;
479 oaktrail_hdmi_teardown(dev
);
480 if (!dev_priv
->has_gct
)
481 psb_intel_destroy_bios(dev
);
484 const struct psb_ops oaktrail_chip_ops
= {
489 .hdmi_mask
= (1 << 0),
490 .lvds_mask
= (1 << 0),
491 .sgx_offset
= MRST_SGX_OFFSET
,
493 .chip_setup
= oaktrail_chip_setup
,
494 .chip_teardown
= oaktrail_teardown
,
495 .crtc_helper
= &oaktrail_helper_funcs
,
496 .crtc_funcs
= &psb_intel_crtc_funcs
,
498 .output_init
= oaktrail_output_init
,
500 #ifdef CONFIG_BACKLIGHT_CLASS_DEVICE
501 .backlight_init
= oaktrail_backlight_init
,
504 .save_regs
= oaktrail_save_display_registers
,
505 .restore_regs
= oaktrail_restore_display_registers
,
506 .power_down
= oaktrail_power_down
,
507 .power_up
= oaktrail_power_up
,