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>
25 #include <drm/gma_drm.h>
28 #include "psb_intel_reg.h"
29 #include <asm/intel-mid.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
);
44 psb_intel_sdvo_init(dev
, SDVOB
);
50 * Provide the low level interfaces for the Moorestown backlight
53 #ifdef CONFIG_BACKLIGHT_CLASS_DEVICE
55 #define MRST_BLC_MAX_PWM_REG_FREQ 0xFFFF
56 #define BLC_PWM_PRECISION_FACTOR 100 /* 10000000 */
57 #define BLC_PWM_FREQ_CALC_CONSTANT 32
59 #define BLC_ADJUSTMENT_MAX 100
61 static struct backlight_device
*oaktrail_backlight_device
;
62 static int oaktrail_brightness
;
64 static int oaktrail_set_brightness(struct backlight_device
*bd
)
66 struct drm_device
*dev
= bl_get_data(oaktrail_backlight_device
);
67 struct drm_psb_private
*dev_priv
= dev
->dev_private
;
68 int level
= bd
->props
.brightness
;
72 /* Percentage 1-100% being valid */
76 if (gma_power_begin(dev
, 0)) {
77 /* Calculate and set the brightness value */
78 max_pwm_blc
= REG_READ(BLC_PWM_CTL
) >> 16;
79 blc_pwm_ctl
= level
* max_pwm_blc
/ 100;
81 /* Adjust the backlight level with the percent in
84 blc_pwm_ctl
= blc_pwm_ctl
* dev_priv
->blc_adj1
;
85 blc_pwm_ctl
= blc_pwm_ctl
/ 100;
87 /* Adjust the backlight level with the percent in
90 blc_pwm_ctl
= blc_pwm_ctl
* dev_priv
->blc_adj2
;
91 blc_pwm_ctl
= blc_pwm_ctl
/ 100;
93 /* force PWM bit on */
94 REG_WRITE(BLC_PWM_CTL2
, (0x80000000 | REG_READ(BLC_PWM_CTL2
)));
95 REG_WRITE(BLC_PWM_CTL
, (max_pwm_blc
<< 16) | blc_pwm_ctl
);
98 oaktrail_brightness
= level
;
102 static int oaktrail_get_brightness(struct backlight_device
*bd
)
104 /* return locally cached var instead of HW read (due to DPST etc.) */
105 /* FIXME: ideally return actual value in case firmware fiddled with
107 return oaktrail_brightness
;
110 static int device_backlight_init(struct drm_device
*dev
)
112 struct drm_psb_private
*dev_priv
= dev
->dev_private
;
113 unsigned long core_clock
;
116 uint32_t blc_pwm_precision_factor
;
118 dev_priv
->blc_adj1
= BLC_ADJUSTMENT_MAX
;
119 dev_priv
->blc_adj2
= BLC_ADJUSTMENT_MAX
;
121 /* this needs to be set elsewhere */
122 blc_pwm_precision_factor
= BLC_PWM_PRECISION_FACTOR
;
124 core_clock
= dev_priv
->core_freq
;
126 value
= (core_clock
* MHz
) / BLC_PWM_FREQ_CALC_CONSTANT
;
127 value
*= blc_pwm_precision_factor
;
128 value
/= bl_max_freq
;
129 value
/= blc_pwm_precision_factor
;
131 if (value
> (unsigned long long)MRST_BLC_MAX_PWM_REG_FREQ
)
134 if (gma_power_begin(dev
, false)) {
135 REG_WRITE(BLC_PWM_CTL2
, (0x80000000 | REG_READ(BLC_PWM_CTL2
)));
136 REG_WRITE(BLC_PWM_CTL
, value
| (value
<< 16));
142 static const struct backlight_ops oaktrail_ops
= {
143 .get_brightness
= oaktrail_get_brightness
,
144 .update_status
= oaktrail_set_brightness
,
147 static int oaktrail_backlight_init(struct drm_device
*dev
)
149 struct drm_psb_private
*dev_priv
= dev
->dev_private
;
151 struct backlight_properties props
;
153 memset(&props
, 0, sizeof(struct backlight_properties
));
154 props
.max_brightness
= 100;
155 props
.type
= BACKLIGHT_PLATFORM
;
157 oaktrail_backlight_device
= backlight_device_register("oaktrail-bl",
158 NULL
, (void *)dev
, &oaktrail_ops
, &props
);
160 if (IS_ERR(oaktrail_backlight_device
))
161 return PTR_ERR(oaktrail_backlight_device
);
163 ret
= device_backlight_init(dev
);
165 backlight_device_unregister(oaktrail_backlight_device
);
168 oaktrail_backlight_device
->props
.brightness
= 100;
169 oaktrail_backlight_device
->props
.max_brightness
= 100;
170 backlight_update_status(oaktrail_backlight_device
);
171 dev_priv
->backlight_device
= oaktrail_backlight_device
;
178 * Provide the Moorestown specific chip logic and low level methods
179 * for power management
183 * oaktrail_save_display_registers - save registers lost on suspend
184 * @dev: our DRM device
186 * Save the state we need in order to be able to restore the interface
187 * upon resume from suspend
189 static int oaktrail_save_display_registers(struct drm_device
*dev
)
191 struct drm_psb_private
*dev_priv
= dev
->dev_private
;
192 struct psb_save_area
*regs
= &dev_priv
->regs
;
193 struct psb_pipe
*p
= ®s
->pipe
[0];
197 /* Display arbitration control + watermarks */
198 regs
->psb
.saveDSPARB
= PSB_RVDC32(DSPARB
);
199 regs
->psb
.saveDSPFW1
= PSB_RVDC32(DSPFW1
);
200 regs
->psb
.saveDSPFW2
= PSB_RVDC32(DSPFW2
);
201 regs
->psb
.saveDSPFW3
= PSB_RVDC32(DSPFW3
);
202 regs
->psb
.saveDSPFW4
= PSB_RVDC32(DSPFW4
);
203 regs
->psb
.saveDSPFW5
= PSB_RVDC32(DSPFW5
);
204 regs
->psb
.saveDSPFW6
= PSB_RVDC32(DSPFW6
);
205 regs
->psb
.saveCHICKENBIT
= PSB_RVDC32(DSPCHICKENBIT
);
207 /* Pipe & plane A info */
208 p
->conf
= PSB_RVDC32(PIPEACONF
);
209 p
->src
= PSB_RVDC32(PIPEASRC
);
210 p
->fp0
= PSB_RVDC32(MRST_FPA0
);
211 p
->fp1
= PSB_RVDC32(MRST_FPA1
);
212 p
->dpll
= PSB_RVDC32(MRST_DPLL_A
);
213 p
->htotal
= PSB_RVDC32(HTOTAL_A
);
214 p
->hblank
= PSB_RVDC32(HBLANK_A
);
215 p
->hsync
= PSB_RVDC32(HSYNC_A
);
216 p
->vtotal
= PSB_RVDC32(VTOTAL_A
);
217 p
->vblank
= PSB_RVDC32(VBLANK_A
);
218 p
->vsync
= PSB_RVDC32(VSYNC_A
);
219 regs
->psb
.saveBCLRPAT_A
= PSB_RVDC32(BCLRPAT_A
);
220 p
->cntr
= PSB_RVDC32(DSPACNTR
);
221 p
->stride
= PSB_RVDC32(DSPASTRIDE
);
222 p
->addr
= PSB_RVDC32(DSPABASE
);
223 p
->surf
= PSB_RVDC32(DSPASURF
);
224 p
->linoff
= PSB_RVDC32(DSPALINOFF
);
225 p
->tileoff
= PSB_RVDC32(DSPATILEOFF
);
227 /* Save cursor regs */
228 regs
->psb
.saveDSPACURSOR_CTRL
= PSB_RVDC32(CURACNTR
);
229 regs
->psb
.saveDSPACURSOR_BASE
= PSB_RVDC32(CURABASE
);
230 regs
->psb
.saveDSPACURSOR_POS
= PSB_RVDC32(CURAPOS
);
232 /* Save palette (gamma) */
233 for (i
= 0; i
< 256; i
++)
234 p
->palette
[i
] = PSB_RVDC32(PALETTE_A
+ (i
<< 2));
236 if (dev_priv
->hdmi_priv
)
237 oaktrail_hdmi_save(dev
);
239 /* Save performance state */
240 regs
->psb
.savePERF_MODE
= PSB_RVDC32(MRST_PERF_MODE
);
243 regs
->psb
.savePP_CONTROL
= PSB_RVDC32(PP_CONTROL
);
244 regs
->psb
.savePFIT_PGM_RATIOS
= PSB_RVDC32(PFIT_PGM_RATIOS
);
245 regs
->psb
.savePFIT_AUTO_RATIOS
= PSB_RVDC32(PFIT_AUTO_RATIOS
);
246 regs
->saveBLC_PWM_CTL
= PSB_RVDC32(BLC_PWM_CTL
);
247 regs
->saveBLC_PWM_CTL2
= PSB_RVDC32(BLC_PWM_CTL2
);
248 regs
->psb
.saveLVDS
= PSB_RVDC32(LVDS
);
249 regs
->psb
.savePFIT_CONTROL
= PSB_RVDC32(PFIT_CONTROL
);
250 regs
->psb
.savePP_ON_DELAYS
= PSB_RVDC32(LVDSPP_ON
);
251 regs
->psb
.savePP_OFF_DELAYS
= PSB_RVDC32(LVDSPP_OFF
);
252 regs
->psb
.savePP_DIVISOR
= PSB_RVDC32(PP_CYCLE
);
255 regs
->psb
.saveOV_OVADD
= PSB_RVDC32(OV_OVADD
);
256 regs
->psb
.saveOV_OGAMC0
= PSB_RVDC32(OV_OGAMC0
);
257 regs
->psb
.saveOV_OGAMC1
= PSB_RVDC32(OV_OGAMC1
);
258 regs
->psb
.saveOV_OGAMC2
= PSB_RVDC32(OV_OGAMC2
);
259 regs
->psb
.saveOV_OGAMC3
= PSB_RVDC32(OV_OGAMC3
);
260 regs
->psb
.saveOV_OGAMC4
= PSB_RVDC32(OV_OGAMC4
);
261 regs
->psb
.saveOV_OGAMC5
= PSB_RVDC32(OV_OGAMC5
);
264 regs
->psb
.saveHISTOGRAM_INT_CONTROL_REG
=
265 PSB_RVDC32(HISTOGRAM_INT_CONTROL
);
266 regs
->psb
.saveHISTOGRAM_LOGIC_CONTROL_REG
=
267 PSB_RVDC32(HISTOGRAM_LOGIC_CONTROL
);
268 regs
->psb
.savePWM_CONTROL_LOGIC
= PSB_RVDC32(PWM_CONTROL_LOGIC
);
270 if (dev_priv
->iLVDS_enable
) {
271 /* Shut down the panel */
272 PSB_WVDC32(0, PP_CONTROL
);
275 pp_stat
= PSB_RVDC32(PP_STATUS
);
276 } while (pp_stat
& 0x80000000);
278 /* Turn off the plane */
279 PSB_WVDC32(0x58000000, DSPACNTR
);
280 /* Trigger the plane disable */
281 PSB_WVDC32(0, DSPASURF
);
287 PSB_WVDC32(0x0, PIPEACONF
);
292 PSB_WVDC32(0, MRST_DPLL_A
);
298 * oaktrail_restore_display_registers - restore lost register state
299 * @dev: our DRM device
301 * Restore register state that was lost during suspend and resume.
303 static int oaktrail_restore_display_registers(struct drm_device
*dev
)
305 struct drm_psb_private
*dev_priv
= dev
->dev_private
;
306 struct psb_save_area
*regs
= &dev_priv
->regs
;
307 struct psb_pipe
*p
= ®s
->pipe
[0];
311 /* Display arbitration + watermarks */
312 PSB_WVDC32(regs
->psb
.saveDSPARB
, DSPARB
);
313 PSB_WVDC32(regs
->psb
.saveDSPFW1
, DSPFW1
);
314 PSB_WVDC32(regs
->psb
.saveDSPFW2
, DSPFW2
);
315 PSB_WVDC32(regs
->psb
.saveDSPFW3
, DSPFW3
);
316 PSB_WVDC32(regs
->psb
.saveDSPFW4
, DSPFW4
);
317 PSB_WVDC32(regs
->psb
.saveDSPFW5
, DSPFW5
);
318 PSB_WVDC32(regs
->psb
.saveDSPFW6
, DSPFW6
);
319 PSB_WVDC32(regs
->psb
.saveCHICKENBIT
, DSPCHICKENBIT
);
321 /* Make sure VGA plane is off. it initializes to on after reset!*/
322 PSB_WVDC32(0x80000000, VGACNTRL
);
325 PSB_WVDC32(p
->fp0
, MRST_FPA0
);
326 PSB_WVDC32(p
->fp1
, MRST_FPA1
);
328 /* Actually enable it */
329 PSB_WVDC32(p
->dpll
, MRST_DPLL_A
);
333 PSB_WVDC32(p
->htotal
, HTOTAL_A
);
334 PSB_WVDC32(p
->hblank
, HBLANK_A
);
335 PSB_WVDC32(p
->hsync
, HSYNC_A
);
336 PSB_WVDC32(p
->vtotal
, VTOTAL_A
);
337 PSB_WVDC32(p
->vblank
, VBLANK_A
);
338 PSB_WVDC32(p
->vsync
, VSYNC_A
);
339 PSB_WVDC32(p
->src
, PIPEASRC
);
340 PSB_WVDC32(regs
->psb
.saveBCLRPAT_A
, BCLRPAT_A
);
342 /* Restore performance mode*/
343 PSB_WVDC32(regs
->psb
.savePERF_MODE
, MRST_PERF_MODE
);
346 if (dev_priv
->iLVDS_enable
)
347 PSB_WVDC32(p
->conf
, PIPEACONF
);
349 /* Set up the plane*/
350 PSB_WVDC32(p
->linoff
, DSPALINOFF
);
351 PSB_WVDC32(p
->stride
, DSPASTRIDE
);
352 PSB_WVDC32(p
->tileoff
, DSPATILEOFF
);
354 /* Enable the plane */
355 PSB_WVDC32(p
->cntr
, DSPACNTR
);
356 PSB_WVDC32(p
->surf
, DSPASURF
);
358 /* Enable Cursor A */
359 PSB_WVDC32(regs
->psb
.saveDSPACURSOR_CTRL
, CURACNTR
);
360 PSB_WVDC32(regs
->psb
.saveDSPACURSOR_POS
, CURAPOS
);
361 PSB_WVDC32(regs
->psb
.saveDSPACURSOR_BASE
, CURABASE
);
363 /* Restore palette (gamma) */
364 for (i
= 0; i
< 256; i
++)
365 PSB_WVDC32(p
->palette
[i
], PALETTE_A
+ (i
<< 2));
367 if (dev_priv
->hdmi_priv
)
368 oaktrail_hdmi_restore(dev
);
370 if (dev_priv
->iLVDS_enable
) {
371 PSB_WVDC32(regs
->saveBLC_PWM_CTL2
, BLC_PWM_CTL2
);
372 PSB_WVDC32(regs
->psb
.saveLVDS
, LVDS
); /*port 61180h*/
373 PSB_WVDC32(regs
->psb
.savePFIT_CONTROL
, PFIT_CONTROL
);
374 PSB_WVDC32(regs
->psb
.savePFIT_PGM_RATIOS
, PFIT_PGM_RATIOS
);
375 PSB_WVDC32(regs
->psb
.savePFIT_AUTO_RATIOS
, PFIT_AUTO_RATIOS
);
376 PSB_WVDC32(regs
->saveBLC_PWM_CTL
, BLC_PWM_CTL
);
377 PSB_WVDC32(regs
->psb
.savePP_ON_DELAYS
, LVDSPP_ON
);
378 PSB_WVDC32(regs
->psb
.savePP_OFF_DELAYS
, LVDSPP_OFF
);
379 PSB_WVDC32(regs
->psb
.savePP_DIVISOR
, PP_CYCLE
);
380 PSB_WVDC32(regs
->psb
.savePP_CONTROL
, PP_CONTROL
);
383 /* Wait for cycle delay */
385 pp_stat
= PSB_RVDC32(PP_STATUS
);
386 } while (pp_stat
& 0x08000000);
388 /* Wait for panel power up */
390 pp_stat
= PSB_RVDC32(PP_STATUS
);
391 } while (pp_stat
& 0x10000000);
393 /* Restore HW overlay */
394 PSB_WVDC32(regs
->psb
.saveOV_OVADD
, OV_OVADD
);
395 PSB_WVDC32(regs
->psb
.saveOV_OGAMC0
, OV_OGAMC0
);
396 PSB_WVDC32(regs
->psb
.saveOV_OGAMC1
, OV_OGAMC1
);
397 PSB_WVDC32(regs
->psb
.saveOV_OGAMC2
, OV_OGAMC2
);
398 PSB_WVDC32(regs
->psb
.saveOV_OGAMC3
, OV_OGAMC3
);
399 PSB_WVDC32(regs
->psb
.saveOV_OGAMC4
, OV_OGAMC4
);
400 PSB_WVDC32(regs
->psb
.saveOV_OGAMC5
, OV_OGAMC5
);
403 PSB_WVDC32(regs
->psb
.saveHISTOGRAM_INT_CONTROL_REG
,
404 HISTOGRAM_INT_CONTROL
);
405 PSB_WVDC32(regs
->psb
.saveHISTOGRAM_LOGIC_CONTROL_REG
,
406 HISTOGRAM_LOGIC_CONTROL
);
407 PSB_WVDC32(regs
->psb
.savePWM_CONTROL_LOGIC
, PWM_CONTROL_LOGIC
);
413 * oaktrail_power_down - power down the display island
414 * @dev: our DRM device
416 * Power down the display interface of our device
418 static int oaktrail_power_down(struct drm_device
*dev
)
420 struct drm_psb_private
*dev_priv
= dev
->dev_private
;
424 pwr_mask
= PSB_PWRGT_DISPLAY_MASK
;
425 outl(pwr_mask
, dev_priv
->ospm_base
+ PSB_PM_SSC
);
428 pwr_sts
= inl(dev_priv
->ospm_base
+ PSB_PM_SSS
);
429 if ((pwr_sts
& pwr_mask
) == pwr_mask
)
440 * Restore power to the specified island(s) (powergating)
442 static int oaktrail_power_up(struct drm_device
*dev
)
444 struct drm_psb_private
*dev_priv
= dev
->dev_private
;
445 u32 pwr_mask
= PSB_PWRGT_DISPLAY_MASK
;
446 u32 pwr_sts
, pwr_cnt
;
448 pwr_cnt
= inl(dev_priv
->ospm_base
+ PSB_PM_SSC
);
449 pwr_cnt
&= ~pwr_mask
;
450 outl(pwr_cnt
, (dev_priv
->ospm_base
+ PSB_PM_SSC
));
453 pwr_sts
= inl(dev_priv
->ospm_base
+ PSB_PM_SSS
);
454 if ((pwr_sts
& pwr_mask
) == 0)
463 static const struct psb_offset oaktrail_regmap
[2] = {
477 .stride
= DSPASTRIDE
,
481 .addr
= MRST_DSPABASE
,
482 .base
= MRST_DSPABASE
,
484 .linoff
= DSPALINOFF
,
485 .tileoff
= DSPATILEOFF
,
486 .palette
= PALETTE_A
,
501 .stride
= DSPBSTRIDE
,
508 .linoff
= DSPBLINOFF
,
509 .tileoff
= DSPBTILEOFF
,
510 .palette
= PALETTE_B
,
514 static int oaktrail_chip_setup(struct drm_device
*dev
)
516 struct drm_psb_private
*dev_priv
= dev
->dev_private
;
519 if (pci_enable_msi(dev
->pdev
))
520 dev_warn(dev
->dev
, "Enabling MSI failed!\n");
522 dev_priv
->regmap
= oaktrail_regmap
;
524 ret
= mid_chip_setup(dev
);
527 if (!dev_priv
->has_gct
) {
528 /* Now pull the BIOS data */
529 psb_intel_opregion_init(dev
);
530 psb_intel_init_bios(dev
);
532 gma_intel_setup_gmbus(dev
);
533 oaktrail_hdmi_setup(dev
);
537 static void oaktrail_teardown(struct drm_device
*dev
)
539 struct drm_psb_private
*dev_priv
= dev
->dev_private
;
541 gma_intel_teardown_gmbus(dev
);
542 oaktrail_hdmi_teardown(dev
);
543 if (!dev_priv
->has_gct
)
544 psb_intel_destroy_bios(dev
);
547 const struct psb_ops oaktrail_chip_ops
= {
552 .hdmi_mask
= (1 << 1),
553 .lvds_mask
= (1 << 0),
554 .sdvo_mask
= (1 << 1),
555 .cursor_needs_phys
= 0,
556 .sgx_offset
= MRST_SGX_OFFSET
,
558 .chip_setup
= oaktrail_chip_setup
,
559 .chip_teardown
= oaktrail_teardown
,
560 .crtc_helper
= &oaktrail_helper_funcs
,
561 .crtc_funcs
= &psb_intel_crtc_funcs
,
563 .output_init
= oaktrail_output_init
,
565 #ifdef CONFIG_BACKLIGHT_CLASS_DEVICE
566 .backlight_init
= oaktrail_backlight_init
,
569 .save_regs
= oaktrail_save_display_registers
,
570 .restore_regs
= oaktrail_restore_display_registers
,
571 .power_down
= oaktrail_power_down
,
572 .power_up
= oaktrail_power_up
,