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
;
190 struct psb_pipe
*p
= ®s
->pipe
[0];
194 /* Display arbitration control + watermarks */
195 regs
->psb
.saveDSPARB
= PSB_RVDC32(DSPARB
);
196 regs
->psb
.saveDSPFW1
= PSB_RVDC32(DSPFW1
);
197 regs
->psb
.saveDSPFW2
= PSB_RVDC32(DSPFW2
);
198 regs
->psb
.saveDSPFW3
= PSB_RVDC32(DSPFW3
);
199 regs
->psb
.saveDSPFW4
= PSB_RVDC32(DSPFW4
);
200 regs
->psb
.saveDSPFW5
= PSB_RVDC32(DSPFW5
);
201 regs
->psb
.saveDSPFW6
= PSB_RVDC32(DSPFW6
);
202 regs
->psb
.saveCHICKENBIT
= PSB_RVDC32(DSPCHICKENBIT
);
204 /* Pipe & plane A info */
205 p
->conf
= PSB_RVDC32(PIPEACONF
);
206 p
->src
= PSB_RVDC32(PIPEASRC
);
207 p
->fp0
= PSB_RVDC32(MRST_FPA0
);
208 p
->fp1
= PSB_RVDC32(MRST_FPA1
);
209 p
->dpll
= PSB_RVDC32(MRST_DPLL_A
);
210 p
->htotal
= PSB_RVDC32(HTOTAL_A
);
211 p
->hblank
= PSB_RVDC32(HBLANK_A
);
212 p
->hsync
= PSB_RVDC32(HSYNC_A
);
213 p
->vtotal
= PSB_RVDC32(VTOTAL_A
);
214 p
->vblank
= PSB_RVDC32(VBLANK_A
);
215 p
->vsync
= PSB_RVDC32(VSYNC_A
);
216 regs
->psb
.saveBCLRPAT_A
= PSB_RVDC32(BCLRPAT_A
);
217 p
->cntr
= PSB_RVDC32(DSPACNTR
);
218 p
->stride
= PSB_RVDC32(DSPASTRIDE
);
219 p
->addr
= PSB_RVDC32(DSPABASE
);
220 p
->surf
= PSB_RVDC32(DSPASURF
);
221 p
->linoff
= PSB_RVDC32(DSPALINOFF
);
222 p
->tileoff
= PSB_RVDC32(DSPATILEOFF
);
224 /* Save cursor regs */
225 regs
->psb
.saveDSPACURSOR_CTRL
= PSB_RVDC32(CURACNTR
);
226 regs
->psb
.saveDSPACURSOR_BASE
= PSB_RVDC32(CURABASE
);
227 regs
->psb
.saveDSPACURSOR_POS
= PSB_RVDC32(CURAPOS
);
229 /* Save palette (gamma) */
230 for (i
= 0; i
< 256; i
++)
231 p
->palette
[i
] = PSB_RVDC32(PALETTE_A
+ (i
<< 2));
233 if (dev_priv
->hdmi_priv
)
234 oaktrail_hdmi_save(dev
);
236 /* Save performance state */
237 regs
->psb
.savePERF_MODE
= PSB_RVDC32(MRST_PERF_MODE
);
240 regs
->psb
.savePP_CONTROL
= PSB_RVDC32(PP_CONTROL
);
241 regs
->psb
.savePFIT_PGM_RATIOS
= PSB_RVDC32(PFIT_PGM_RATIOS
);
242 regs
->psb
.savePFIT_AUTO_RATIOS
= PSB_RVDC32(PFIT_AUTO_RATIOS
);
243 regs
->saveBLC_PWM_CTL
= PSB_RVDC32(BLC_PWM_CTL
);
244 regs
->saveBLC_PWM_CTL2
= PSB_RVDC32(BLC_PWM_CTL2
);
245 regs
->psb
.saveLVDS
= PSB_RVDC32(LVDS
);
246 regs
->psb
.savePFIT_CONTROL
= PSB_RVDC32(PFIT_CONTROL
);
247 regs
->psb
.savePP_ON_DELAYS
= PSB_RVDC32(LVDSPP_ON
);
248 regs
->psb
.savePP_OFF_DELAYS
= PSB_RVDC32(LVDSPP_OFF
);
249 regs
->psb
.savePP_DIVISOR
= PSB_RVDC32(PP_CYCLE
);
252 regs
->psb
.saveOV_OVADD
= PSB_RVDC32(OV_OVADD
);
253 regs
->psb
.saveOV_OGAMC0
= PSB_RVDC32(OV_OGAMC0
);
254 regs
->psb
.saveOV_OGAMC1
= PSB_RVDC32(OV_OGAMC1
);
255 regs
->psb
.saveOV_OGAMC2
= PSB_RVDC32(OV_OGAMC2
);
256 regs
->psb
.saveOV_OGAMC3
= PSB_RVDC32(OV_OGAMC3
);
257 regs
->psb
.saveOV_OGAMC4
= PSB_RVDC32(OV_OGAMC4
);
258 regs
->psb
.saveOV_OGAMC5
= PSB_RVDC32(OV_OGAMC5
);
261 regs
->psb
.saveHISTOGRAM_INT_CONTROL_REG
=
262 PSB_RVDC32(HISTOGRAM_INT_CONTROL
);
263 regs
->psb
.saveHISTOGRAM_LOGIC_CONTROL_REG
=
264 PSB_RVDC32(HISTOGRAM_LOGIC_CONTROL
);
265 regs
->psb
.savePWM_CONTROL_LOGIC
= PSB_RVDC32(PWM_CONTROL_LOGIC
);
267 if (dev_priv
->iLVDS_enable
) {
268 /* Shut down the panel */
269 PSB_WVDC32(0, PP_CONTROL
);
272 pp_stat
= PSB_RVDC32(PP_STATUS
);
273 } while (pp_stat
& 0x80000000);
275 /* Turn off the plane */
276 PSB_WVDC32(0x58000000, DSPACNTR
);
277 /* Trigger the plane disable */
278 PSB_WVDC32(0, DSPASURF
);
284 PSB_WVDC32(0x0, PIPEACONF
);
289 PSB_WVDC32(0, MRST_DPLL_A
);
295 * oaktrail_restore_display_registers - restore lost register state
296 * @dev: our DRM device
298 * Restore register state that was lost during suspend and resume.
300 static int oaktrail_restore_display_registers(struct drm_device
*dev
)
302 struct drm_psb_private
*dev_priv
= dev
->dev_private
;
303 struct psb_save_area
*regs
= &dev_priv
->regs
;
304 struct psb_pipe
*p
= ®s
->pipe
[0];
308 /* Display arbitration + watermarks */
309 PSB_WVDC32(regs
->psb
.saveDSPARB
, DSPARB
);
310 PSB_WVDC32(regs
->psb
.saveDSPFW1
, DSPFW1
);
311 PSB_WVDC32(regs
->psb
.saveDSPFW2
, DSPFW2
);
312 PSB_WVDC32(regs
->psb
.saveDSPFW3
, DSPFW3
);
313 PSB_WVDC32(regs
->psb
.saveDSPFW4
, DSPFW4
);
314 PSB_WVDC32(regs
->psb
.saveDSPFW5
, DSPFW5
);
315 PSB_WVDC32(regs
->psb
.saveDSPFW6
, DSPFW6
);
316 PSB_WVDC32(regs
->psb
.saveCHICKENBIT
, DSPCHICKENBIT
);
318 /* Make sure VGA plane is off. it initializes to on after reset!*/
319 PSB_WVDC32(0x80000000, VGACNTRL
);
322 PSB_WVDC32(p
->fp0
, MRST_FPA0
);
323 PSB_WVDC32(p
->fp1
, MRST_FPA1
);
325 /* Actually enable it */
326 PSB_WVDC32(p
->dpll
, MRST_DPLL_A
);
330 PSB_WVDC32(p
->htotal
, HTOTAL_A
);
331 PSB_WVDC32(p
->hblank
, HBLANK_A
);
332 PSB_WVDC32(p
->hsync
, HSYNC_A
);
333 PSB_WVDC32(p
->vtotal
, VTOTAL_A
);
334 PSB_WVDC32(p
->vblank
, VBLANK_A
);
335 PSB_WVDC32(p
->vsync
, VSYNC_A
);
336 PSB_WVDC32(p
->src
, PIPEASRC
);
337 PSB_WVDC32(regs
->psb
.saveBCLRPAT_A
, BCLRPAT_A
);
339 /* Restore performance mode*/
340 PSB_WVDC32(regs
->psb
.savePERF_MODE
, MRST_PERF_MODE
);
343 if (dev_priv
->iLVDS_enable
)
344 PSB_WVDC32(p
->conf
, PIPEACONF
);
346 /* Set up the plane*/
347 PSB_WVDC32(p
->linoff
, DSPALINOFF
);
348 PSB_WVDC32(p
->stride
, DSPASTRIDE
);
349 PSB_WVDC32(p
->tileoff
, DSPATILEOFF
);
351 /* Enable the plane */
352 PSB_WVDC32(p
->cntr
, DSPACNTR
);
353 PSB_WVDC32(p
->surf
, DSPASURF
);
355 /* Enable Cursor A */
356 PSB_WVDC32(regs
->psb
.saveDSPACURSOR_CTRL
, CURACNTR
);
357 PSB_WVDC32(regs
->psb
.saveDSPACURSOR_POS
, CURAPOS
);
358 PSB_WVDC32(regs
->psb
.saveDSPACURSOR_BASE
, CURABASE
);
360 /* Restore palette (gamma) */
361 for (i
= 0; i
< 256; i
++)
362 PSB_WVDC32(p
->palette
[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(regs
->saveBLC_PWM_CTL2
, BLC_PWM_CTL2
);
369 PSB_WVDC32(regs
->psb
.saveLVDS
, LVDS
); /*port 61180h*/
370 PSB_WVDC32(regs
->psb
.savePFIT_CONTROL
, PFIT_CONTROL
);
371 PSB_WVDC32(regs
->psb
.savePFIT_PGM_RATIOS
, PFIT_PGM_RATIOS
);
372 PSB_WVDC32(regs
->psb
.savePFIT_AUTO_RATIOS
, PFIT_AUTO_RATIOS
);
373 PSB_WVDC32(regs
->saveBLC_PWM_CTL
, BLC_PWM_CTL
);
374 PSB_WVDC32(regs
->psb
.savePP_ON_DELAYS
, LVDSPP_ON
);
375 PSB_WVDC32(regs
->psb
.savePP_OFF_DELAYS
, LVDSPP_OFF
);
376 PSB_WVDC32(regs
->psb
.savePP_DIVISOR
, PP_CYCLE
);
377 PSB_WVDC32(regs
->psb
.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(regs
->psb
.saveOV_OVADD
, OV_OVADD
);
392 PSB_WVDC32(regs
->psb
.saveOV_OGAMC0
, OV_OGAMC0
);
393 PSB_WVDC32(regs
->psb
.saveOV_OGAMC1
, OV_OGAMC1
);
394 PSB_WVDC32(regs
->psb
.saveOV_OGAMC2
, OV_OGAMC2
);
395 PSB_WVDC32(regs
->psb
.saveOV_OGAMC3
, OV_OGAMC3
);
396 PSB_WVDC32(regs
->psb
.saveOV_OGAMC4
, OV_OGAMC4
);
397 PSB_WVDC32(regs
->psb
.saveOV_OGAMC5
, OV_OGAMC5
);
400 PSB_WVDC32(regs
->psb
.saveHISTOGRAM_INT_CONTROL_REG
,
401 HISTOGRAM_INT_CONTROL
);
402 PSB_WVDC32(regs
->psb
.saveHISTOGRAM_LOGIC_CONTROL_REG
,
403 HISTOGRAM_LOGIC_CONTROL
);
404 PSB_WVDC32(regs
->psb
.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 const struct psb_offset oaktrail_regmap
[2] = {
474 .stride
= DSPASTRIDE
,
478 .addr
= MRST_DSPABASE
,
480 .linoff
= DSPALINOFF
,
481 .tileoff
= DSPATILEOFF
,
482 .palette
= PALETTE_A
,
497 .stride
= DSPBSTRIDE
,
503 .linoff
= DSPBLINOFF
,
504 .tileoff
= DSPBTILEOFF
,
505 .palette
= PALETTE_B
,
509 static int oaktrail_chip_setup(struct drm_device
*dev
)
511 struct drm_psb_private
*dev_priv
= dev
->dev_private
;
514 if (pci_enable_msi(dev
->pdev
))
515 dev_warn(dev
->dev
, "Enabling MSI failed!\n");
517 dev_priv
->regmap
= oaktrail_regmap
;
519 ret
= mid_chip_setup(dev
);
522 if (!dev_priv
->has_gct
) {
523 /* Now pull the BIOS data */
524 psb_intel_opregion_init(dev
);
525 psb_intel_init_bios(dev
);
527 oaktrail_hdmi_setup(dev
);
531 static void oaktrail_teardown(struct drm_device
*dev
)
533 struct drm_psb_private
*dev_priv
= dev
->dev_private
;
535 oaktrail_hdmi_teardown(dev
);
536 if (!dev_priv
->has_gct
)
537 psb_intel_destroy_bios(dev
);
540 const struct psb_ops oaktrail_chip_ops
= {
545 .hdmi_mask
= (1 << 0),
546 .lvds_mask
= (1 << 0),
547 .cursor_needs_phys
= 0,
548 .sgx_offset
= MRST_SGX_OFFSET
,
550 .chip_setup
= oaktrail_chip_setup
,
551 .chip_teardown
= oaktrail_teardown
,
552 .crtc_helper
= &oaktrail_helper_funcs
,
553 .crtc_funcs
= &psb_intel_crtc_funcs
,
555 .output_init
= oaktrail_output_init
,
557 #ifdef CONFIG_BACKLIGHT_CLASS_DEVICE
558 .backlight_init
= oaktrail_backlight_init
,
561 .save_regs
= oaktrail_save_display_registers
,
562 .restore_regs
= oaktrail_restore_display_registers
,
563 .power_down
= oaktrail_power_down
,
564 .power_up
= oaktrail_power_up
,