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>
15 #include "intel_bios.h"
18 #include "psb_intel_reg.h"
21 static int oaktrail_output_init(struct drm_device
*dev
)
23 struct drm_psb_private
*dev_priv
= to_drm_psb_private(dev
);
24 if (dev_priv
->iLVDS_enable
)
25 oaktrail_lvds_init(dev
, &dev_priv
->mode_dev
);
27 dev_err(dev
->dev
, "DSI is not supported\n");
28 if (dev_priv
->hdmi_priv
)
29 oaktrail_hdmi_init(dev
, &dev_priv
->mode_dev
);
31 psb_intel_sdvo_init(dev
, SDVOB
);
37 * Provide the low level interfaces for the Moorestown backlight
40 #ifdef CONFIG_BACKLIGHT_CLASS_DEVICE
42 #define MRST_BLC_MAX_PWM_REG_FREQ 0xFFFF
43 #define BLC_PWM_PRECISION_FACTOR 100 /* 10000000 */
44 #define BLC_PWM_FREQ_CALC_CONSTANT 32
46 #define BLC_ADJUSTMENT_MAX 100
48 static struct backlight_device
*oaktrail_backlight_device
;
49 static int oaktrail_brightness
;
51 static int oaktrail_set_brightness(struct backlight_device
*bd
)
53 struct drm_device
*dev
= bl_get_data(oaktrail_backlight_device
);
54 struct drm_psb_private
*dev_priv
= to_drm_psb_private(dev
);
55 int level
= bd
->props
.brightness
;
59 /* Percentage 1-100% being valid */
63 if (gma_power_begin(dev
, 0)) {
64 /* Calculate and set the brightness value */
65 max_pwm_blc
= REG_READ(BLC_PWM_CTL
) >> 16;
66 blc_pwm_ctl
= level
* max_pwm_blc
/ 100;
68 /* Adjust the backlight level with the percent in
71 blc_pwm_ctl
= blc_pwm_ctl
* dev_priv
->blc_adj1
;
72 blc_pwm_ctl
= blc_pwm_ctl
/ 100;
74 /* Adjust the backlight level with the percent in
77 blc_pwm_ctl
= blc_pwm_ctl
* dev_priv
->blc_adj2
;
78 blc_pwm_ctl
= blc_pwm_ctl
/ 100;
80 /* force PWM bit on */
81 REG_WRITE(BLC_PWM_CTL2
, (0x80000000 | REG_READ(BLC_PWM_CTL2
)));
82 REG_WRITE(BLC_PWM_CTL
, (max_pwm_blc
<< 16) | blc_pwm_ctl
);
85 oaktrail_brightness
= level
;
89 static int oaktrail_get_brightness(struct backlight_device
*bd
)
91 /* return locally cached var instead of HW read (due to DPST etc.) */
92 /* FIXME: ideally return actual value in case firmware fiddled with
94 return oaktrail_brightness
;
97 static int device_backlight_init(struct drm_device
*dev
)
99 struct drm_psb_private
*dev_priv
= to_drm_psb_private(dev
);
100 unsigned long core_clock
;
103 uint32_t blc_pwm_precision_factor
;
105 dev_priv
->blc_adj1
= BLC_ADJUSTMENT_MAX
;
106 dev_priv
->blc_adj2
= BLC_ADJUSTMENT_MAX
;
108 /* this needs to be set elsewhere */
109 blc_pwm_precision_factor
= BLC_PWM_PRECISION_FACTOR
;
111 core_clock
= dev_priv
->core_freq
;
113 value
= (core_clock
* MHz
) / BLC_PWM_FREQ_CALC_CONSTANT
;
114 value
*= blc_pwm_precision_factor
;
115 value
/= bl_max_freq
;
116 value
/= blc_pwm_precision_factor
;
118 if (value
> (unsigned long long)MRST_BLC_MAX_PWM_REG_FREQ
)
121 if (gma_power_begin(dev
, false)) {
122 REG_WRITE(BLC_PWM_CTL2
, (0x80000000 | REG_READ(BLC_PWM_CTL2
)));
123 REG_WRITE(BLC_PWM_CTL
, value
| (value
<< 16));
129 static const struct backlight_ops oaktrail_ops
= {
130 .get_brightness
= oaktrail_get_brightness
,
131 .update_status
= oaktrail_set_brightness
,
134 static int oaktrail_backlight_init(struct drm_device
*dev
)
136 struct drm_psb_private
*dev_priv
= to_drm_psb_private(dev
);
138 struct backlight_properties props
;
140 memset(&props
, 0, sizeof(struct backlight_properties
));
141 props
.max_brightness
= 100;
142 props
.type
= BACKLIGHT_PLATFORM
;
144 oaktrail_backlight_device
= backlight_device_register("oaktrail-bl",
145 NULL
, (void *)dev
, &oaktrail_ops
, &props
);
147 if (IS_ERR(oaktrail_backlight_device
))
148 return PTR_ERR(oaktrail_backlight_device
);
150 ret
= device_backlight_init(dev
);
152 backlight_device_unregister(oaktrail_backlight_device
);
155 oaktrail_backlight_device
->props
.brightness
= 100;
156 oaktrail_backlight_device
->props
.max_brightness
= 100;
157 backlight_update_status(oaktrail_backlight_device
);
158 dev_priv
->backlight_device
= oaktrail_backlight_device
;
165 * Provide the Moorestown specific chip logic and low level methods
166 * for power management
170 * oaktrail_save_display_registers - save registers lost on suspend
171 * @dev: our DRM device
173 * Save the state we need in order to be able to restore the interface
174 * upon resume from suspend
176 static int oaktrail_save_display_registers(struct drm_device
*dev
)
178 struct drm_psb_private
*dev_priv
= to_drm_psb_private(dev
);
179 struct psb_save_area
*regs
= &dev_priv
->regs
;
180 struct psb_pipe
*p
= ®s
->pipe
[0];
184 /* Display arbitration control + watermarks */
185 regs
->psb
.saveDSPARB
= PSB_RVDC32(DSPARB
);
186 regs
->psb
.saveDSPFW1
= PSB_RVDC32(DSPFW1
);
187 regs
->psb
.saveDSPFW2
= PSB_RVDC32(DSPFW2
);
188 regs
->psb
.saveDSPFW3
= PSB_RVDC32(DSPFW3
);
189 regs
->psb
.saveDSPFW4
= PSB_RVDC32(DSPFW4
);
190 regs
->psb
.saveDSPFW5
= PSB_RVDC32(DSPFW5
);
191 regs
->psb
.saveDSPFW6
= PSB_RVDC32(DSPFW6
);
192 regs
->psb
.saveCHICKENBIT
= PSB_RVDC32(DSPCHICKENBIT
);
194 /* Pipe & plane A info */
195 p
->conf
= PSB_RVDC32(PIPEACONF
);
196 p
->src
= PSB_RVDC32(PIPEASRC
);
197 p
->fp0
= PSB_RVDC32(MRST_FPA0
);
198 p
->fp1
= PSB_RVDC32(MRST_FPA1
);
199 p
->dpll
= PSB_RVDC32(MRST_DPLL_A
);
200 p
->htotal
= PSB_RVDC32(HTOTAL_A
);
201 p
->hblank
= PSB_RVDC32(HBLANK_A
);
202 p
->hsync
= PSB_RVDC32(HSYNC_A
);
203 p
->vtotal
= PSB_RVDC32(VTOTAL_A
);
204 p
->vblank
= PSB_RVDC32(VBLANK_A
);
205 p
->vsync
= PSB_RVDC32(VSYNC_A
);
206 regs
->psb
.saveBCLRPAT_A
= PSB_RVDC32(BCLRPAT_A
);
207 p
->cntr
= PSB_RVDC32(DSPACNTR
);
208 p
->stride
= PSB_RVDC32(DSPASTRIDE
);
209 p
->addr
= PSB_RVDC32(DSPABASE
);
210 p
->surf
= PSB_RVDC32(DSPASURF
);
211 p
->linoff
= PSB_RVDC32(DSPALINOFF
);
212 p
->tileoff
= PSB_RVDC32(DSPATILEOFF
);
214 /* Save cursor regs */
215 regs
->psb
.saveDSPACURSOR_CTRL
= PSB_RVDC32(CURACNTR
);
216 regs
->psb
.saveDSPACURSOR_BASE
= PSB_RVDC32(CURABASE
);
217 regs
->psb
.saveDSPACURSOR_POS
= PSB_RVDC32(CURAPOS
);
219 /* Save palette (gamma) */
220 for (i
= 0; i
< 256; i
++)
221 p
->palette
[i
] = PSB_RVDC32(PALETTE_A
+ (i
<< 2));
223 if (dev_priv
->hdmi_priv
)
224 oaktrail_hdmi_save(dev
);
226 /* Save performance state */
227 regs
->psb
.savePERF_MODE
= PSB_RVDC32(MRST_PERF_MODE
);
230 regs
->psb
.savePP_CONTROL
= PSB_RVDC32(PP_CONTROL
);
231 regs
->psb
.savePFIT_PGM_RATIOS
= PSB_RVDC32(PFIT_PGM_RATIOS
);
232 regs
->psb
.savePFIT_AUTO_RATIOS
= PSB_RVDC32(PFIT_AUTO_RATIOS
);
233 regs
->saveBLC_PWM_CTL
= PSB_RVDC32(BLC_PWM_CTL
);
234 regs
->saveBLC_PWM_CTL2
= PSB_RVDC32(BLC_PWM_CTL2
);
235 regs
->psb
.saveLVDS
= PSB_RVDC32(LVDS
);
236 regs
->psb
.savePFIT_CONTROL
= PSB_RVDC32(PFIT_CONTROL
);
237 regs
->psb
.savePP_ON_DELAYS
= PSB_RVDC32(LVDSPP_ON
);
238 regs
->psb
.savePP_OFF_DELAYS
= PSB_RVDC32(LVDSPP_OFF
);
239 regs
->psb
.savePP_DIVISOR
= PSB_RVDC32(PP_CYCLE
);
242 regs
->psb
.saveOV_OVADD
= PSB_RVDC32(OV_OVADD
);
243 regs
->psb
.saveOV_OGAMC0
= PSB_RVDC32(OV_OGAMC0
);
244 regs
->psb
.saveOV_OGAMC1
= PSB_RVDC32(OV_OGAMC1
);
245 regs
->psb
.saveOV_OGAMC2
= PSB_RVDC32(OV_OGAMC2
);
246 regs
->psb
.saveOV_OGAMC3
= PSB_RVDC32(OV_OGAMC3
);
247 regs
->psb
.saveOV_OGAMC4
= PSB_RVDC32(OV_OGAMC4
);
248 regs
->psb
.saveOV_OGAMC5
= PSB_RVDC32(OV_OGAMC5
);
251 regs
->psb
.saveHISTOGRAM_INT_CONTROL_REG
=
252 PSB_RVDC32(HISTOGRAM_INT_CONTROL
);
253 regs
->psb
.saveHISTOGRAM_LOGIC_CONTROL_REG
=
254 PSB_RVDC32(HISTOGRAM_LOGIC_CONTROL
);
255 regs
->psb
.savePWM_CONTROL_LOGIC
= PSB_RVDC32(PWM_CONTROL_LOGIC
);
257 if (dev_priv
->iLVDS_enable
) {
258 /* Shut down the panel */
259 PSB_WVDC32(0, PP_CONTROL
);
262 pp_stat
= PSB_RVDC32(PP_STATUS
);
263 } while (pp_stat
& 0x80000000);
265 /* Turn off the plane */
266 PSB_WVDC32(0x58000000, DSPACNTR
);
267 /* Trigger the plane disable */
268 PSB_WVDC32(0, DSPASURF
);
274 PSB_WVDC32(0x0, PIPEACONF
);
279 PSB_WVDC32(0, MRST_DPLL_A
);
285 * oaktrail_restore_display_registers - restore lost register state
286 * @dev: our DRM device
288 * Restore register state that was lost during suspend and resume.
290 static int oaktrail_restore_display_registers(struct drm_device
*dev
)
292 struct drm_psb_private
*dev_priv
= to_drm_psb_private(dev
);
293 struct psb_save_area
*regs
= &dev_priv
->regs
;
294 struct psb_pipe
*p
= ®s
->pipe
[0];
298 /* Display arbitration + watermarks */
299 PSB_WVDC32(regs
->psb
.saveDSPARB
, DSPARB
);
300 PSB_WVDC32(regs
->psb
.saveDSPFW1
, DSPFW1
);
301 PSB_WVDC32(regs
->psb
.saveDSPFW2
, DSPFW2
);
302 PSB_WVDC32(regs
->psb
.saveDSPFW3
, DSPFW3
);
303 PSB_WVDC32(regs
->psb
.saveDSPFW4
, DSPFW4
);
304 PSB_WVDC32(regs
->psb
.saveDSPFW5
, DSPFW5
);
305 PSB_WVDC32(regs
->psb
.saveDSPFW6
, DSPFW6
);
306 PSB_WVDC32(regs
->psb
.saveCHICKENBIT
, DSPCHICKENBIT
);
308 /* Make sure VGA plane is off. it initializes to on after reset!*/
309 PSB_WVDC32(0x80000000, VGACNTRL
);
312 PSB_WVDC32(p
->fp0
, MRST_FPA0
);
313 PSB_WVDC32(p
->fp1
, MRST_FPA1
);
315 /* Actually enable it */
316 PSB_WVDC32(p
->dpll
, MRST_DPLL_A
);
320 PSB_WVDC32(p
->htotal
, HTOTAL_A
);
321 PSB_WVDC32(p
->hblank
, HBLANK_A
);
322 PSB_WVDC32(p
->hsync
, HSYNC_A
);
323 PSB_WVDC32(p
->vtotal
, VTOTAL_A
);
324 PSB_WVDC32(p
->vblank
, VBLANK_A
);
325 PSB_WVDC32(p
->vsync
, VSYNC_A
);
326 PSB_WVDC32(p
->src
, PIPEASRC
);
327 PSB_WVDC32(regs
->psb
.saveBCLRPAT_A
, BCLRPAT_A
);
329 /* Restore performance mode*/
330 PSB_WVDC32(regs
->psb
.savePERF_MODE
, MRST_PERF_MODE
);
333 if (dev_priv
->iLVDS_enable
)
334 PSB_WVDC32(p
->conf
, PIPEACONF
);
336 /* Set up the plane*/
337 PSB_WVDC32(p
->linoff
, DSPALINOFF
);
338 PSB_WVDC32(p
->stride
, DSPASTRIDE
);
339 PSB_WVDC32(p
->tileoff
, DSPATILEOFF
);
341 /* Enable the plane */
342 PSB_WVDC32(p
->cntr
, DSPACNTR
);
343 PSB_WVDC32(p
->surf
, DSPASURF
);
345 /* Enable Cursor A */
346 PSB_WVDC32(regs
->psb
.saveDSPACURSOR_CTRL
, CURACNTR
);
347 PSB_WVDC32(regs
->psb
.saveDSPACURSOR_POS
, CURAPOS
);
348 PSB_WVDC32(regs
->psb
.saveDSPACURSOR_BASE
, CURABASE
);
350 /* Restore palette (gamma) */
351 for (i
= 0; i
< 256; i
++)
352 PSB_WVDC32(p
->palette
[i
], PALETTE_A
+ (i
<< 2));
354 if (dev_priv
->hdmi_priv
)
355 oaktrail_hdmi_restore(dev
);
357 if (dev_priv
->iLVDS_enable
) {
358 PSB_WVDC32(regs
->saveBLC_PWM_CTL2
, BLC_PWM_CTL2
);
359 PSB_WVDC32(regs
->psb
.saveLVDS
, LVDS
); /*port 61180h*/
360 PSB_WVDC32(regs
->psb
.savePFIT_CONTROL
, PFIT_CONTROL
);
361 PSB_WVDC32(regs
->psb
.savePFIT_PGM_RATIOS
, PFIT_PGM_RATIOS
);
362 PSB_WVDC32(regs
->psb
.savePFIT_AUTO_RATIOS
, PFIT_AUTO_RATIOS
);
363 PSB_WVDC32(regs
->saveBLC_PWM_CTL
, BLC_PWM_CTL
);
364 PSB_WVDC32(regs
->psb
.savePP_ON_DELAYS
, LVDSPP_ON
);
365 PSB_WVDC32(regs
->psb
.savePP_OFF_DELAYS
, LVDSPP_OFF
);
366 PSB_WVDC32(regs
->psb
.savePP_DIVISOR
, PP_CYCLE
);
367 PSB_WVDC32(regs
->psb
.savePP_CONTROL
, PP_CONTROL
);
370 /* Wait for cycle delay */
372 pp_stat
= PSB_RVDC32(PP_STATUS
);
373 } while (pp_stat
& 0x08000000);
375 /* Wait for panel power up */
377 pp_stat
= PSB_RVDC32(PP_STATUS
);
378 } while (pp_stat
& 0x10000000);
380 /* Restore HW overlay */
381 PSB_WVDC32(regs
->psb
.saveOV_OVADD
, OV_OVADD
);
382 PSB_WVDC32(regs
->psb
.saveOV_OGAMC0
, OV_OGAMC0
);
383 PSB_WVDC32(regs
->psb
.saveOV_OGAMC1
, OV_OGAMC1
);
384 PSB_WVDC32(regs
->psb
.saveOV_OGAMC2
, OV_OGAMC2
);
385 PSB_WVDC32(regs
->psb
.saveOV_OGAMC3
, OV_OGAMC3
);
386 PSB_WVDC32(regs
->psb
.saveOV_OGAMC4
, OV_OGAMC4
);
387 PSB_WVDC32(regs
->psb
.saveOV_OGAMC5
, OV_OGAMC5
);
390 PSB_WVDC32(regs
->psb
.saveHISTOGRAM_INT_CONTROL_REG
,
391 HISTOGRAM_INT_CONTROL
);
392 PSB_WVDC32(regs
->psb
.saveHISTOGRAM_LOGIC_CONTROL_REG
,
393 HISTOGRAM_LOGIC_CONTROL
);
394 PSB_WVDC32(regs
->psb
.savePWM_CONTROL_LOGIC
, PWM_CONTROL_LOGIC
);
400 * oaktrail_power_down - power down the display island
401 * @dev: our DRM device
403 * Power down the display interface of our device
405 static int oaktrail_power_down(struct drm_device
*dev
)
407 struct drm_psb_private
*dev_priv
= to_drm_psb_private(dev
);
411 pwr_mask
= PSB_PWRGT_DISPLAY_MASK
;
412 outl(pwr_mask
, dev_priv
->ospm_base
+ PSB_PM_SSC
);
415 pwr_sts
= inl(dev_priv
->ospm_base
+ PSB_PM_SSS
);
416 if ((pwr_sts
& pwr_mask
) == pwr_mask
)
427 * Restore power to the specified island(s) (powergating)
429 static int oaktrail_power_up(struct drm_device
*dev
)
431 struct drm_psb_private
*dev_priv
= to_drm_psb_private(dev
);
432 u32 pwr_mask
= PSB_PWRGT_DISPLAY_MASK
;
433 u32 pwr_sts
, pwr_cnt
;
435 pwr_cnt
= inl(dev_priv
->ospm_base
+ PSB_PM_SSC
);
436 pwr_cnt
&= ~pwr_mask
;
437 outl(pwr_cnt
, (dev_priv
->ospm_base
+ PSB_PM_SSC
));
440 pwr_sts
= inl(dev_priv
->ospm_base
+ PSB_PM_SSS
);
441 if ((pwr_sts
& pwr_mask
) == 0)
450 static const struct psb_offset oaktrail_regmap
[2] = {
464 .stride
= DSPASTRIDE
,
468 .addr
= MRST_DSPABASE
,
469 .base
= MRST_DSPABASE
,
471 .linoff
= DSPALINOFF
,
472 .tileoff
= DSPATILEOFF
,
473 .palette
= PALETTE_A
,
488 .stride
= DSPBSTRIDE
,
495 .linoff
= DSPBLINOFF
,
496 .tileoff
= DSPBTILEOFF
,
497 .palette
= PALETTE_B
,
501 static int oaktrail_chip_setup(struct drm_device
*dev
)
503 struct drm_psb_private
*dev_priv
= to_drm_psb_private(dev
);
506 dev_priv
->use_msi
= true;
507 dev_priv
->regmap
= oaktrail_regmap
;
509 ret
= mid_chip_setup(dev
);
512 if (!dev_priv
->has_gct
) {
513 /* Now pull the BIOS data */
514 psb_intel_opregion_init(dev
);
515 psb_intel_init_bios(dev
);
517 gma_intel_setup_gmbus(dev
);
518 oaktrail_hdmi_setup(dev
);
522 static void oaktrail_teardown(struct drm_device
*dev
)
524 struct drm_psb_private
*dev_priv
= to_drm_psb_private(dev
);
526 gma_intel_teardown_gmbus(dev
);
527 oaktrail_hdmi_teardown(dev
);
528 if (!dev_priv
->has_gct
)
529 psb_intel_destroy_bios(dev
);
532 const struct psb_ops oaktrail_chip_ops
= {
536 .hdmi_mask
= (1 << 1),
537 .lvds_mask
= (1 << 0),
538 .sdvo_mask
= (1 << 1),
539 .cursor_needs_phys
= 0,
540 .sgx_offset
= MRST_SGX_OFFSET
,
542 .chip_setup
= oaktrail_chip_setup
,
543 .chip_teardown
= oaktrail_teardown
,
544 .crtc_helper
= &oaktrail_helper_funcs
,
546 .output_init
= oaktrail_output_init
,
548 #ifdef CONFIG_BACKLIGHT_CLASS_DEVICE
549 .backlight_init
= oaktrail_backlight_init
,
552 .save_regs
= oaktrail_save_display_registers
,
553 .restore_regs
= oaktrail_restore_display_registers
,
554 .save_crtc
= gma_crtc_save
,
555 .restore_crtc
= gma_crtc_restore
,
556 .power_down
= oaktrail_power_down
,
557 .power_up
= oaktrail_power_up
,