1 // SPDX-License-Identifier: GPL-2.0-only
2 /**************************************************************************
3 * Copyright (c) 2011, Intel Corporation.
6 **************************************************************************/
8 #include <linux/backlight.h>
9 #include <linux/delay.h>
10 #include <linux/dmi.h>
11 #include <linux/module.h>
13 #include <asm/intel-mid.h>
14 #include <asm/intel_scu_ipc.h>
18 #include "intel_bios.h"
21 #include "psb_intel_reg.h"
24 static int oaktrail_output_init(struct drm_device
*dev
)
26 struct drm_psb_private
*dev_priv
= dev
->dev_private
;
27 if (dev_priv
->iLVDS_enable
)
28 oaktrail_lvds_init(dev
, &dev_priv
->mode_dev
);
30 dev_err(dev
->dev
, "DSI is not supported\n");
31 if (dev_priv
->hdmi_priv
)
32 oaktrail_hdmi_init(dev
, &dev_priv
->mode_dev
);
34 psb_intel_sdvo_init(dev
, SDVOB
);
40 * Provide the low level interfaces for the Moorestown backlight
43 #ifdef CONFIG_BACKLIGHT_CLASS_DEVICE
45 #define MRST_BLC_MAX_PWM_REG_FREQ 0xFFFF
46 #define BLC_PWM_PRECISION_FACTOR 100 /* 10000000 */
47 #define BLC_PWM_FREQ_CALC_CONSTANT 32
49 #define BLC_ADJUSTMENT_MAX 100
51 static struct backlight_device
*oaktrail_backlight_device
;
52 static int oaktrail_brightness
;
54 static int oaktrail_set_brightness(struct backlight_device
*bd
)
56 struct drm_device
*dev
= bl_get_data(oaktrail_backlight_device
);
57 struct drm_psb_private
*dev_priv
= dev
->dev_private
;
58 int level
= bd
->props
.brightness
;
62 /* Percentage 1-100% being valid */
66 if (gma_power_begin(dev
, 0)) {
67 /* Calculate and set the brightness value */
68 max_pwm_blc
= REG_READ(BLC_PWM_CTL
) >> 16;
69 blc_pwm_ctl
= level
* max_pwm_blc
/ 100;
71 /* Adjust the backlight level with the percent in
74 blc_pwm_ctl
= blc_pwm_ctl
* dev_priv
->blc_adj1
;
75 blc_pwm_ctl
= blc_pwm_ctl
/ 100;
77 /* Adjust the backlight level with the percent in
80 blc_pwm_ctl
= blc_pwm_ctl
* dev_priv
->blc_adj2
;
81 blc_pwm_ctl
= blc_pwm_ctl
/ 100;
83 /* force PWM bit on */
84 REG_WRITE(BLC_PWM_CTL2
, (0x80000000 | REG_READ(BLC_PWM_CTL2
)));
85 REG_WRITE(BLC_PWM_CTL
, (max_pwm_blc
<< 16) | blc_pwm_ctl
);
88 oaktrail_brightness
= level
;
92 static int oaktrail_get_brightness(struct backlight_device
*bd
)
94 /* return locally cached var instead of HW read (due to DPST etc.) */
95 /* FIXME: ideally return actual value in case firmware fiddled with
97 return oaktrail_brightness
;
100 static int device_backlight_init(struct drm_device
*dev
)
102 struct drm_psb_private
*dev_priv
= dev
->dev_private
;
103 unsigned long core_clock
;
106 uint32_t blc_pwm_precision_factor
;
108 dev_priv
->blc_adj1
= BLC_ADJUSTMENT_MAX
;
109 dev_priv
->blc_adj2
= BLC_ADJUSTMENT_MAX
;
111 /* this needs to be set elsewhere */
112 blc_pwm_precision_factor
= BLC_PWM_PRECISION_FACTOR
;
114 core_clock
= dev_priv
->core_freq
;
116 value
= (core_clock
* MHz
) / BLC_PWM_FREQ_CALC_CONSTANT
;
117 value
*= blc_pwm_precision_factor
;
118 value
/= bl_max_freq
;
119 value
/= blc_pwm_precision_factor
;
121 if (value
> (unsigned long long)MRST_BLC_MAX_PWM_REG_FREQ
)
124 if (gma_power_begin(dev
, false)) {
125 REG_WRITE(BLC_PWM_CTL2
, (0x80000000 | REG_READ(BLC_PWM_CTL2
)));
126 REG_WRITE(BLC_PWM_CTL
, value
| (value
<< 16));
132 static const struct backlight_ops oaktrail_ops
= {
133 .get_brightness
= oaktrail_get_brightness
,
134 .update_status
= oaktrail_set_brightness
,
137 static int oaktrail_backlight_init(struct drm_device
*dev
)
139 struct drm_psb_private
*dev_priv
= dev
->dev_private
;
141 struct backlight_properties props
;
143 memset(&props
, 0, sizeof(struct backlight_properties
));
144 props
.max_brightness
= 100;
145 props
.type
= BACKLIGHT_PLATFORM
;
147 oaktrail_backlight_device
= backlight_device_register("oaktrail-bl",
148 NULL
, (void *)dev
, &oaktrail_ops
, &props
);
150 if (IS_ERR(oaktrail_backlight_device
))
151 return PTR_ERR(oaktrail_backlight_device
);
153 ret
= device_backlight_init(dev
);
155 backlight_device_unregister(oaktrail_backlight_device
);
158 oaktrail_backlight_device
->props
.brightness
= 100;
159 oaktrail_backlight_device
->props
.max_brightness
= 100;
160 backlight_update_status(oaktrail_backlight_device
);
161 dev_priv
->backlight_device
= oaktrail_backlight_device
;
168 * Provide the Moorestown specific chip logic and low level methods
169 * for power management
173 * oaktrail_save_display_registers - save registers lost on suspend
174 * @dev: our DRM device
176 * Save the state we need in order to be able to restore the interface
177 * upon resume from suspend
179 static int oaktrail_save_display_registers(struct drm_device
*dev
)
181 struct drm_psb_private
*dev_priv
= dev
->dev_private
;
182 struct psb_save_area
*regs
= &dev_priv
->regs
;
183 struct psb_pipe
*p
= ®s
->pipe
[0];
187 /* Display arbitration control + watermarks */
188 regs
->psb
.saveDSPARB
= PSB_RVDC32(DSPARB
);
189 regs
->psb
.saveDSPFW1
= PSB_RVDC32(DSPFW1
);
190 regs
->psb
.saveDSPFW2
= PSB_RVDC32(DSPFW2
);
191 regs
->psb
.saveDSPFW3
= PSB_RVDC32(DSPFW3
);
192 regs
->psb
.saveDSPFW4
= PSB_RVDC32(DSPFW4
);
193 regs
->psb
.saveDSPFW5
= PSB_RVDC32(DSPFW5
);
194 regs
->psb
.saveDSPFW6
= PSB_RVDC32(DSPFW6
);
195 regs
->psb
.saveCHICKENBIT
= PSB_RVDC32(DSPCHICKENBIT
);
197 /* Pipe & plane A info */
198 p
->conf
= PSB_RVDC32(PIPEACONF
);
199 p
->src
= PSB_RVDC32(PIPEASRC
);
200 p
->fp0
= PSB_RVDC32(MRST_FPA0
);
201 p
->fp1
= PSB_RVDC32(MRST_FPA1
);
202 p
->dpll
= PSB_RVDC32(MRST_DPLL_A
);
203 p
->htotal
= PSB_RVDC32(HTOTAL_A
);
204 p
->hblank
= PSB_RVDC32(HBLANK_A
);
205 p
->hsync
= PSB_RVDC32(HSYNC_A
);
206 p
->vtotal
= PSB_RVDC32(VTOTAL_A
);
207 p
->vblank
= PSB_RVDC32(VBLANK_A
);
208 p
->vsync
= PSB_RVDC32(VSYNC_A
);
209 regs
->psb
.saveBCLRPAT_A
= PSB_RVDC32(BCLRPAT_A
);
210 p
->cntr
= PSB_RVDC32(DSPACNTR
);
211 p
->stride
= PSB_RVDC32(DSPASTRIDE
);
212 p
->addr
= PSB_RVDC32(DSPABASE
);
213 p
->surf
= PSB_RVDC32(DSPASURF
);
214 p
->linoff
= PSB_RVDC32(DSPALINOFF
);
215 p
->tileoff
= PSB_RVDC32(DSPATILEOFF
);
217 /* Save cursor regs */
218 regs
->psb
.saveDSPACURSOR_CTRL
= PSB_RVDC32(CURACNTR
);
219 regs
->psb
.saveDSPACURSOR_BASE
= PSB_RVDC32(CURABASE
);
220 regs
->psb
.saveDSPACURSOR_POS
= PSB_RVDC32(CURAPOS
);
222 /* Save palette (gamma) */
223 for (i
= 0; i
< 256; i
++)
224 p
->palette
[i
] = PSB_RVDC32(PALETTE_A
+ (i
<< 2));
226 if (dev_priv
->hdmi_priv
)
227 oaktrail_hdmi_save(dev
);
229 /* Save performance state */
230 regs
->psb
.savePERF_MODE
= PSB_RVDC32(MRST_PERF_MODE
);
233 regs
->psb
.savePP_CONTROL
= PSB_RVDC32(PP_CONTROL
);
234 regs
->psb
.savePFIT_PGM_RATIOS
= PSB_RVDC32(PFIT_PGM_RATIOS
);
235 regs
->psb
.savePFIT_AUTO_RATIOS
= PSB_RVDC32(PFIT_AUTO_RATIOS
);
236 regs
->saveBLC_PWM_CTL
= PSB_RVDC32(BLC_PWM_CTL
);
237 regs
->saveBLC_PWM_CTL2
= PSB_RVDC32(BLC_PWM_CTL2
);
238 regs
->psb
.saveLVDS
= PSB_RVDC32(LVDS
);
239 regs
->psb
.savePFIT_CONTROL
= PSB_RVDC32(PFIT_CONTROL
);
240 regs
->psb
.savePP_ON_DELAYS
= PSB_RVDC32(LVDSPP_ON
);
241 regs
->psb
.savePP_OFF_DELAYS
= PSB_RVDC32(LVDSPP_OFF
);
242 regs
->psb
.savePP_DIVISOR
= PSB_RVDC32(PP_CYCLE
);
245 regs
->psb
.saveOV_OVADD
= PSB_RVDC32(OV_OVADD
);
246 regs
->psb
.saveOV_OGAMC0
= PSB_RVDC32(OV_OGAMC0
);
247 regs
->psb
.saveOV_OGAMC1
= PSB_RVDC32(OV_OGAMC1
);
248 regs
->psb
.saveOV_OGAMC2
= PSB_RVDC32(OV_OGAMC2
);
249 regs
->psb
.saveOV_OGAMC3
= PSB_RVDC32(OV_OGAMC3
);
250 regs
->psb
.saveOV_OGAMC4
= PSB_RVDC32(OV_OGAMC4
);
251 regs
->psb
.saveOV_OGAMC5
= PSB_RVDC32(OV_OGAMC5
);
254 regs
->psb
.saveHISTOGRAM_INT_CONTROL_REG
=
255 PSB_RVDC32(HISTOGRAM_INT_CONTROL
);
256 regs
->psb
.saveHISTOGRAM_LOGIC_CONTROL_REG
=
257 PSB_RVDC32(HISTOGRAM_LOGIC_CONTROL
);
258 regs
->psb
.savePWM_CONTROL_LOGIC
= PSB_RVDC32(PWM_CONTROL_LOGIC
);
260 if (dev_priv
->iLVDS_enable
) {
261 /* Shut down the panel */
262 PSB_WVDC32(0, PP_CONTROL
);
265 pp_stat
= PSB_RVDC32(PP_STATUS
);
266 } while (pp_stat
& 0x80000000);
268 /* Turn off the plane */
269 PSB_WVDC32(0x58000000, DSPACNTR
);
270 /* Trigger the plane disable */
271 PSB_WVDC32(0, DSPASURF
);
277 PSB_WVDC32(0x0, PIPEACONF
);
282 PSB_WVDC32(0, MRST_DPLL_A
);
288 * oaktrail_restore_display_registers - restore lost register state
289 * @dev: our DRM device
291 * Restore register state that was lost during suspend and resume.
293 static int oaktrail_restore_display_registers(struct drm_device
*dev
)
295 struct drm_psb_private
*dev_priv
= dev
->dev_private
;
296 struct psb_save_area
*regs
= &dev_priv
->regs
;
297 struct psb_pipe
*p
= ®s
->pipe
[0];
301 /* Display arbitration + watermarks */
302 PSB_WVDC32(regs
->psb
.saveDSPARB
, DSPARB
);
303 PSB_WVDC32(regs
->psb
.saveDSPFW1
, DSPFW1
);
304 PSB_WVDC32(regs
->psb
.saveDSPFW2
, DSPFW2
);
305 PSB_WVDC32(regs
->psb
.saveDSPFW3
, DSPFW3
);
306 PSB_WVDC32(regs
->psb
.saveDSPFW4
, DSPFW4
);
307 PSB_WVDC32(regs
->psb
.saveDSPFW5
, DSPFW5
);
308 PSB_WVDC32(regs
->psb
.saveDSPFW6
, DSPFW6
);
309 PSB_WVDC32(regs
->psb
.saveCHICKENBIT
, DSPCHICKENBIT
);
311 /* Make sure VGA plane is off. it initializes to on after reset!*/
312 PSB_WVDC32(0x80000000, VGACNTRL
);
315 PSB_WVDC32(p
->fp0
, MRST_FPA0
);
316 PSB_WVDC32(p
->fp1
, MRST_FPA1
);
318 /* Actually enable it */
319 PSB_WVDC32(p
->dpll
, MRST_DPLL_A
);
323 PSB_WVDC32(p
->htotal
, HTOTAL_A
);
324 PSB_WVDC32(p
->hblank
, HBLANK_A
);
325 PSB_WVDC32(p
->hsync
, HSYNC_A
);
326 PSB_WVDC32(p
->vtotal
, VTOTAL_A
);
327 PSB_WVDC32(p
->vblank
, VBLANK_A
);
328 PSB_WVDC32(p
->vsync
, VSYNC_A
);
329 PSB_WVDC32(p
->src
, PIPEASRC
);
330 PSB_WVDC32(regs
->psb
.saveBCLRPAT_A
, BCLRPAT_A
);
332 /* Restore performance mode*/
333 PSB_WVDC32(regs
->psb
.savePERF_MODE
, MRST_PERF_MODE
);
336 if (dev_priv
->iLVDS_enable
)
337 PSB_WVDC32(p
->conf
, PIPEACONF
);
339 /* Set up the plane*/
340 PSB_WVDC32(p
->linoff
, DSPALINOFF
);
341 PSB_WVDC32(p
->stride
, DSPASTRIDE
);
342 PSB_WVDC32(p
->tileoff
, DSPATILEOFF
);
344 /* Enable the plane */
345 PSB_WVDC32(p
->cntr
, DSPACNTR
);
346 PSB_WVDC32(p
->surf
, DSPASURF
);
348 /* Enable Cursor A */
349 PSB_WVDC32(regs
->psb
.saveDSPACURSOR_CTRL
, CURACNTR
);
350 PSB_WVDC32(regs
->psb
.saveDSPACURSOR_POS
, CURAPOS
);
351 PSB_WVDC32(regs
->psb
.saveDSPACURSOR_BASE
, CURABASE
);
353 /* Restore palette (gamma) */
354 for (i
= 0; i
< 256; i
++)
355 PSB_WVDC32(p
->palette
[i
], PALETTE_A
+ (i
<< 2));
357 if (dev_priv
->hdmi_priv
)
358 oaktrail_hdmi_restore(dev
);
360 if (dev_priv
->iLVDS_enable
) {
361 PSB_WVDC32(regs
->saveBLC_PWM_CTL2
, BLC_PWM_CTL2
);
362 PSB_WVDC32(regs
->psb
.saveLVDS
, LVDS
); /*port 61180h*/
363 PSB_WVDC32(regs
->psb
.savePFIT_CONTROL
, PFIT_CONTROL
);
364 PSB_WVDC32(regs
->psb
.savePFIT_PGM_RATIOS
, PFIT_PGM_RATIOS
);
365 PSB_WVDC32(regs
->psb
.savePFIT_AUTO_RATIOS
, PFIT_AUTO_RATIOS
);
366 PSB_WVDC32(regs
->saveBLC_PWM_CTL
, BLC_PWM_CTL
);
367 PSB_WVDC32(regs
->psb
.savePP_ON_DELAYS
, LVDSPP_ON
);
368 PSB_WVDC32(regs
->psb
.savePP_OFF_DELAYS
, LVDSPP_OFF
);
369 PSB_WVDC32(regs
->psb
.savePP_DIVISOR
, PP_CYCLE
);
370 PSB_WVDC32(regs
->psb
.savePP_CONTROL
, PP_CONTROL
);
373 /* Wait for cycle delay */
375 pp_stat
= PSB_RVDC32(PP_STATUS
);
376 } while (pp_stat
& 0x08000000);
378 /* Wait for panel power up */
380 pp_stat
= PSB_RVDC32(PP_STATUS
);
381 } while (pp_stat
& 0x10000000);
383 /* Restore HW overlay */
384 PSB_WVDC32(regs
->psb
.saveOV_OVADD
, OV_OVADD
);
385 PSB_WVDC32(regs
->psb
.saveOV_OGAMC0
, OV_OGAMC0
);
386 PSB_WVDC32(regs
->psb
.saveOV_OGAMC1
, OV_OGAMC1
);
387 PSB_WVDC32(regs
->psb
.saveOV_OGAMC2
, OV_OGAMC2
);
388 PSB_WVDC32(regs
->psb
.saveOV_OGAMC3
, OV_OGAMC3
);
389 PSB_WVDC32(regs
->psb
.saveOV_OGAMC4
, OV_OGAMC4
);
390 PSB_WVDC32(regs
->psb
.saveOV_OGAMC5
, OV_OGAMC5
);
393 PSB_WVDC32(regs
->psb
.saveHISTOGRAM_INT_CONTROL_REG
,
394 HISTOGRAM_INT_CONTROL
);
395 PSB_WVDC32(regs
->psb
.saveHISTOGRAM_LOGIC_CONTROL_REG
,
396 HISTOGRAM_LOGIC_CONTROL
);
397 PSB_WVDC32(regs
->psb
.savePWM_CONTROL_LOGIC
, PWM_CONTROL_LOGIC
);
403 * oaktrail_power_down - power down the display island
404 * @dev: our DRM device
406 * Power down the display interface of our device
408 static int oaktrail_power_down(struct drm_device
*dev
)
410 struct drm_psb_private
*dev_priv
= dev
->dev_private
;
414 pwr_mask
= PSB_PWRGT_DISPLAY_MASK
;
415 outl(pwr_mask
, dev_priv
->ospm_base
+ PSB_PM_SSC
);
418 pwr_sts
= inl(dev_priv
->ospm_base
+ PSB_PM_SSS
);
419 if ((pwr_sts
& pwr_mask
) == pwr_mask
)
430 * Restore power to the specified island(s) (powergating)
432 static int oaktrail_power_up(struct drm_device
*dev
)
434 struct drm_psb_private
*dev_priv
= dev
->dev_private
;
435 u32 pwr_mask
= PSB_PWRGT_DISPLAY_MASK
;
436 u32 pwr_sts
, pwr_cnt
;
438 pwr_cnt
= inl(dev_priv
->ospm_base
+ PSB_PM_SSC
);
439 pwr_cnt
&= ~pwr_mask
;
440 outl(pwr_cnt
, (dev_priv
->ospm_base
+ PSB_PM_SSC
));
443 pwr_sts
= inl(dev_priv
->ospm_base
+ PSB_PM_SSS
);
444 if ((pwr_sts
& pwr_mask
) == 0)
453 static const struct psb_offset oaktrail_regmap
[2] = {
467 .stride
= DSPASTRIDE
,
471 .addr
= MRST_DSPABASE
,
472 .base
= MRST_DSPABASE
,
474 .linoff
= DSPALINOFF
,
475 .tileoff
= DSPATILEOFF
,
476 .palette
= PALETTE_A
,
491 .stride
= DSPBSTRIDE
,
498 .linoff
= DSPBLINOFF
,
499 .tileoff
= DSPBTILEOFF
,
500 .palette
= PALETTE_B
,
504 static int oaktrail_chip_setup(struct drm_device
*dev
)
506 struct drm_psb_private
*dev_priv
= dev
->dev_private
;
509 if (pci_enable_msi(dev
->pdev
))
510 dev_warn(dev
->dev
, "Enabling MSI failed!\n");
512 dev_priv
->regmap
= oaktrail_regmap
;
514 ret
= mid_chip_setup(dev
);
517 if (!dev_priv
->has_gct
) {
518 /* Now pull the BIOS data */
519 psb_intel_opregion_init(dev
);
520 psb_intel_init_bios(dev
);
522 gma_intel_setup_gmbus(dev
);
523 oaktrail_hdmi_setup(dev
);
527 static void oaktrail_teardown(struct drm_device
*dev
)
529 struct drm_psb_private
*dev_priv
= dev
->dev_private
;
531 gma_intel_teardown_gmbus(dev
);
532 oaktrail_hdmi_teardown(dev
);
533 if (!dev_priv
->has_gct
)
534 psb_intel_destroy_bios(dev
);
537 const struct psb_ops oaktrail_chip_ops
= {
541 .hdmi_mask
= (1 << 1),
542 .lvds_mask
= (1 << 0),
543 .sdvo_mask
= (1 << 1),
544 .cursor_needs_phys
= 0,
545 .sgx_offset
= MRST_SGX_OFFSET
,
547 .chip_setup
= oaktrail_chip_setup
,
548 .chip_teardown
= oaktrail_teardown
,
549 .crtc_helper
= &oaktrail_helper_funcs
,
550 .crtc_funcs
= &psb_intel_crtc_funcs
,
552 .output_init
= oaktrail_output_init
,
554 #ifdef CONFIG_BACKLIGHT_CLASS_DEVICE
555 .backlight_init
= oaktrail_backlight_init
,
558 .save_regs
= oaktrail_save_display_registers
,
559 .restore_regs
= oaktrail_restore_display_registers
,
560 .save_crtc
= gma_crtc_save
,
561 .restore_crtc
= gma_crtc_restore
,
562 .power_down
= oaktrail_power_down
,
563 .power_up
= oaktrail_power_up
,