1 // SPDX-License-Identifier: GPL-2.0-only
2 /**************************************************************************
3 * Copyright (c) 2011, Intel Corporation.
6 **************************************************************************/
10 #include "mdfld_output.h"
11 #include "mdfld_dsi_output.h"
12 #include "tc35876x-dsi-lvds.h"
14 #include <asm/intel_scu_ipc.h>
16 #ifdef CONFIG_BACKLIGHT_CLASS_DEVICE
18 #define MRST_BLC_MAX_PWM_REG_FREQ 0xFFFF
19 #define BLC_PWM_PRECISION_FACTOR 100 /* 10000000 */
20 #define BLC_PWM_FREQ_CALC_CONSTANT 32
22 #define BRIGHTNESS_MIN_LEVEL 1
23 #define BRIGHTNESS_MAX_LEVEL 100
24 #define BRIGHTNESS_MASK 0xFF
25 #define BLC_POLARITY_NORMAL 0
26 #define BLC_POLARITY_INVERSE 1
27 #define BLC_ADJUSTMENT_MAX 100
29 #define MDFLD_BLC_PWM_PRECISION_FACTOR 10
30 #define MDFLD_BLC_MAX_PWM_REG_FREQ 0xFFFE
31 #define MDFLD_BLC_MIN_PWM_REG_FREQ 0x2
33 #define MDFLD_BACKLIGHT_PWM_POLARITY_BIT_CLEAR (0xFFFE)
34 #define MDFLD_BACKLIGHT_PWM_CTL_SHIFT (16)
36 static struct backlight_device
*mdfld_backlight_device
;
38 int mdfld_set_brightness(struct backlight_device
*bd
)
40 struct drm_device
*dev
=
41 (struct drm_device
*)bl_get_data(mdfld_backlight_device
);
42 struct drm_psb_private
*dev_priv
= dev
->dev_private
;
43 int level
= bd
->props
.brightness
;
45 DRM_DEBUG_DRIVER("backlight level set to %d\n", level
);
47 /* Perform value bounds checking */
48 if (level
< BRIGHTNESS_MIN_LEVEL
)
49 level
= BRIGHTNESS_MIN_LEVEL
;
51 if (gma_power_begin(dev
, false)) {
52 u32 adjusted_level
= 0;
55 * Adjust the backlight level with the percent in
58 adjusted_level
= level
* dev_priv
->blc_adj2
;
59 adjusted_level
= adjusted_level
/ BLC_ADJUSTMENT_MAX
;
60 dev_priv
->brightness_adjusted
= adjusted_level
;
62 if (mdfld_get_panel_type(dev
, 0) == TC35876X
) {
63 if (dev_priv
->dpi_panel_on
[0] ||
64 dev_priv
->dpi_panel_on
[2])
65 tc35876x_brightness_control(dev
,
66 dev_priv
->brightness_adjusted
);
68 if (dev_priv
->dpi_panel_on
[0])
69 mdfld_dsi_brightness_control(dev
, 0,
70 dev_priv
->brightness_adjusted
);
73 if (dev_priv
->dpi_panel_on
[2])
74 mdfld_dsi_brightness_control(dev
, 2,
75 dev_priv
->brightness_adjusted
);
79 /* cache the brightness for later use */
80 dev_priv
->brightness
= level
;
84 static int mdfld_get_brightness(struct backlight_device
*bd
)
86 struct drm_device
*dev
=
87 (struct drm_device
*)bl_get_data(mdfld_backlight_device
);
88 struct drm_psb_private
*dev_priv
= dev
->dev_private
;
90 DRM_DEBUG_DRIVER("brightness = 0x%x \n", dev_priv
->brightness
);
92 /* return locally cached var instead of HW read (due to DPST etc.) */
93 return dev_priv
->brightness
;
96 static const struct backlight_ops mdfld_ops
= {
97 .get_brightness
= mdfld_get_brightness
,
98 .update_status
= mdfld_set_brightness
,
101 static int device_backlight_init(struct drm_device
*dev
)
103 struct drm_psb_private
*dev_priv
= (struct drm_psb_private
*)
106 dev_priv
->blc_adj1
= BLC_ADJUSTMENT_MAX
;
107 dev_priv
->blc_adj2
= BLC_ADJUSTMENT_MAX
;
112 static int mdfld_backlight_init(struct drm_device
*dev
)
114 struct backlight_properties props
;
117 memset(&props
, 0, sizeof(struct backlight_properties
));
118 props
.max_brightness
= BRIGHTNESS_MAX_LEVEL
;
119 props
.type
= BACKLIGHT_PLATFORM
;
120 mdfld_backlight_device
= backlight_device_register("mdfld-bl",
121 NULL
, (void *)dev
, &mdfld_ops
, &props
);
123 if (IS_ERR(mdfld_backlight_device
))
124 return PTR_ERR(mdfld_backlight_device
);
126 ret
= device_backlight_init(dev
);
130 mdfld_backlight_device
->props
.brightness
= BRIGHTNESS_MAX_LEVEL
;
131 mdfld_backlight_device
->props
.max_brightness
= BRIGHTNESS_MAX_LEVEL
;
132 backlight_update_status(mdfld_backlight_device
);
137 struct backlight_device
*mdfld_get_backlight_device(void)
139 #ifdef CONFIG_BACKLIGHT_CLASS_DEVICE
140 return mdfld_backlight_device
;
147 * mdfld_save_display_registers
149 * Description: We are going to suspend so save current display
152 * Notes: FIXME_JLIU7 need to add the support for DPI MIPI & HDMI audio
154 static int mdfld_save_display_registers(struct drm_device
*dev
, int pipenum
)
156 struct drm_psb_private
*dev_priv
= dev
->dev_private
;
157 struct medfield_state
*regs
= &dev_priv
->regs
.mdfld
;
158 struct psb_pipe
*pipe
= &dev_priv
->regs
.pipe
[pipenum
];
159 const struct psb_offset
*map
= &dev_priv
->regmap
[pipenum
];
168 mipi_val
= ®s
->saveMIPI
;
171 mipi_val
= ®s
->saveMIPI
;
176 /* pointer to values */
177 mipi_val
= ®s
->saveMIPI_C
;
180 DRM_ERROR("%s, invalid pipe number.\n", __func__
);
184 /* Pipe & plane A info */
185 pipe
->dpll
= PSB_RVDC32(map
->dpll
);
186 pipe
->fp0
= PSB_RVDC32(map
->fp0
);
187 pipe
->conf
= PSB_RVDC32(map
->conf
);
188 pipe
->htotal
= PSB_RVDC32(map
->htotal
);
189 pipe
->hblank
= PSB_RVDC32(map
->hblank
);
190 pipe
->hsync
= PSB_RVDC32(map
->hsync
);
191 pipe
->vtotal
= PSB_RVDC32(map
->vtotal
);
192 pipe
->vblank
= PSB_RVDC32(map
->vblank
);
193 pipe
->vsync
= PSB_RVDC32(map
->vsync
);
194 pipe
->src
= PSB_RVDC32(map
->src
);
195 pipe
->stride
= PSB_RVDC32(map
->stride
);
196 pipe
->linoff
= PSB_RVDC32(map
->linoff
);
197 pipe
->tileoff
= PSB_RVDC32(map
->tileoff
);
198 pipe
->size
= PSB_RVDC32(map
->size
);
199 pipe
->pos
= PSB_RVDC32(map
->pos
);
200 pipe
->surf
= PSB_RVDC32(map
->surf
);
201 pipe
->cntr
= PSB_RVDC32(map
->cntr
);
202 pipe
->status
= PSB_RVDC32(map
->status
);
204 /*save palette (gamma) */
205 for (i
= 0; i
< 256; i
++)
206 pipe
->palette
[i
] = PSB_RVDC32(map
->palette
+ (i
<< 2));
209 regs
->savePFIT_CONTROL
= PSB_RVDC32(PFIT_CONTROL
);
210 regs
->savePFIT_PGM_RATIOS
= PSB_RVDC32(PFIT_PGM_RATIOS
);
212 regs
->saveHDMIPHYMISCCTL
= PSB_RVDC32(HDMIPHYMISCCTL
);
213 regs
->saveHDMIB_CONTROL
= PSB_RVDC32(HDMIB_CONTROL
);
217 *mipi_val
= PSB_RVDC32(mipi_reg
);
222 * mdfld_restore_display_registers
224 * Description: We are going to resume so restore display register state.
226 * Notes: FIXME_JLIU7 need to add the support for DPI MIPI & HDMI audio
228 static int mdfld_restore_display_registers(struct drm_device
*dev
, int pipenum
)
230 /* To get panel out of ULPS mode. */
232 u32 device_ready_reg
= DEVICE_READY_REG
;
233 struct drm_psb_private
*dev_priv
= dev
->dev_private
;
234 struct mdfld_dsi_config
*dsi_config
= NULL
;
235 struct medfield_state
*regs
= &dev_priv
->regs
.mdfld
;
236 struct psb_pipe
*pipe
= &dev_priv
->regs
.pipe
[pipenum
];
237 const struct psb_offset
*map
= &dev_priv
->regmap
[pipenum
];
246 u32 dpll_val
= pipe
->dpll
;
247 u32 mipi_val
= regs
->saveMIPI
;
251 dpll_val
&= ~DPLL_VCO_ENABLE
;
252 dsi_config
= dev_priv
->dsi_configs
[0];
255 dpll_val
&= ~DPLL_VCO_ENABLE
;
259 mipi_val
= regs
->saveMIPI_C
;
260 dsi_config
= dev_priv
->dsi_configs
[1];
263 DRM_ERROR("%s, invalid pipe number.\n", __func__
);
267 /*make sure VGA plane is off. it initializes to on after reset!*/
268 PSB_WVDC32(0x80000000, VGACNTRL
);
271 PSB_WVDC32(dpll_val
& ~DPLL_VCO_ENABLE
, map
->dpll
);
272 PSB_RVDC32(map
->dpll
);
274 PSB_WVDC32(pipe
->fp0
, map
->fp0
);
277 dpll
= PSB_RVDC32(map
->dpll
);
279 if (!(dpll
& DPLL_VCO_ENABLE
)) {
281 /* When ungating power of DPLL, needs to wait 0.5us
282 before enable the VCO */
283 if (dpll
& MDFLD_PWR_GATE_EN
) {
284 dpll
&= ~MDFLD_PWR_GATE_EN
;
285 PSB_WVDC32(dpll
, map
->dpll
);
286 /* FIXME_MDFLD PO - change 500 to 1 after PO */
290 PSB_WVDC32(pipe
->fp0
, map
->fp0
);
291 PSB_WVDC32(dpll_val
, map
->dpll
);
292 /* FIXME_MDFLD PO - change 500 to 1 after PO */
295 dpll_val
|= DPLL_VCO_ENABLE
;
296 PSB_WVDC32(dpll_val
, map
->dpll
);
297 PSB_RVDC32(map
->dpll
);
299 /* wait for DSI PLL to lock */
300 while (timeout
< 20000 &&
301 !(PSB_RVDC32(map
->conf
) & PIPECONF_DSIPLL_LOCK
)) {
306 if (timeout
== 20000) {
307 DRM_ERROR("%s, can't lock DSIPLL.\n",
314 PSB_WVDC32(pipe
->htotal
, map
->htotal
);
315 PSB_WVDC32(pipe
->hblank
, map
->hblank
);
316 PSB_WVDC32(pipe
->hsync
, map
->hsync
);
317 PSB_WVDC32(pipe
->vtotal
, map
->vtotal
);
318 PSB_WVDC32(pipe
->vblank
, map
->vblank
);
319 PSB_WVDC32(pipe
->vsync
, map
->vsync
);
320 PSB_WVDC32(pipe
->src
, map
->src
);
321 PSB_WVDC32(pipe
->status
, map
->status
);
324 PSB_WVDC32(pipe
->stride
, map
->stride
);
325 PSB_WVDC32(pipe
->linoff
, map
->linoff
);
326 PSB_WVDC32(pipe
->tileoff
, map
->tileoff
);
327 PSB_WVDC32(pipe
->size
, map
->size
);
328 PSB_WVDC32(pipe
->pos
, map
->pos
);
329 PSB_WVDC32(pipe
->surf
, map
->surf
);
332 /* restore palette (gamma) */
333 /*DRM_UDELAY(50000); */
334 for (i
= 0; i
< 256; i
++)
335 PSB_WVDC32(pipe
->palette
[i
], map
->palette
+ (i
<< 2));
337 PSB_WVDC32(regs
->savePFIT_CONTROL
, PFIT_CONTROL
);
338 PSB_WVDC32(regs
->savePFIT_PGM_RATIOS
, PFIT_PGM_RATIOS
);
340 /*TODO: resume HDMI port */
342 /*TODO: resume pipe*/
345 PSB_WVDC32(pipe
->cntr
& ~DISPLAY_PLANE_ENABLE
, map
->cntr
);
350 /*set up pipe related registers*/
351 PSB_WVDC32(mipi_val
, mipi_reg
);
353 /*setup MIPI adapter + MIPI IP registers*/
355 mdfld_dsi_controller_init(dsi_config
, pipenum
);
357 if (in_atomic() || in_interrupt())
363 PSB_WVDC32(pipe
->cntr
, map
->cntr
);
365 if (in_atomic() || in_interrupt())
370 /* LP Hold Release */
371 temp
= REG_READ(mipi_reg
);
372 temp
|= LP_OUTPUT_HOLD_RELEASE
;
373 REG_WRITE(mipi_reg
, temp
);
377 /* Set DSI host to exit from Utra Low Power State */
378 temp
= REG_READ(device_ready_reg
);
381 temp
|= EXIT_ULPS_DEV_READY
;
382 REG_WRITE(device_ready_reg
, temp
);
385 temp
= REG_READ(device_ready_reg
);
387 temp
|= EXITING_ULPS
;
388 REG_WRITE(device_ready_reg
, temp
);
392 PSB_WVDC32(pipe
->conf
, map
->conf
);
394 /* restore palette (gamma) */
395 /*DRM_UDELAY(50000); */
396 for (i
= 0; i
< 256; i
++)
397 PSB_WVDC32(pipe
->palette
[i
], map
->palette
+ (i
<< 2));
402 static int mdfld_save_registers(struct drm_device
*dev
)
404 /* mdfld_save_cursor_overlay_registers(dev); */
405 mdfld_save_display_registers(dev
, 0);
406 mdfld_save_display_registers(dev
, 2);
407 mdfld_disable_crtc(dev
, 0);
408 mdfld_disable_crtc(dev
, 2);
413 static int mdfld_restore_registers(struct drm_device
*dev
)
415 mdfld_restore_display_registers(dev
, 2);
416 mdfld_restore_display_registers(dev
, 0);
417 /* mdfld_restore_cursor_overlay_registers(dev); */
422 static int mdfld_power_down(struct drm_device
*dev
)
428 static int mdfld_power_up(struct drm_device
*dev
)
435 static const struct psb_offset mdfld_regmap
[3] = {
449 .stride
= DSPASTRIDE
,
453 .addr
= MRST_DSPABASE
,
455 .linoff
= DSPALINOFF
,
456 .tileoff
= DSPATILEOFF
,
457 .palette
= PALETTE_A
,
460 .fp0
= MDFLD_DPLL_DIV0
,
464 .dpll
= MDFLD_DPLL_B
,
471 .stride
= DSPBSTRIDE
,
475 .addr
= MRST_DSPBBASE
,
477 .linoff
= DSPBLINOFF
,
478 .tileoff
= DSPBTILEOFF
,
479 .palette
= PALETTE_B
,
482 .fp0
= MRST_FPA0
, /* This is what the old code did ?? */
494 .stride
= DSPCSTRIDE
,
498 .addr
= MDFLD_DSPCBASE
,
500 .linoff
= DSPCLINOFF
,
501 .tileoff
= DSPCTILEOFF
,
502 .palette
= PALETTE_C
,
506 static int mdfld_chip_setup(struct drm_device
*dev
)
508 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");
511 dev_priv
->regmap
= mdfld_regmap
;
512 return mid_chip_setup(dev
);
515 const struct psb_ops mdfld_chip_ops
= {
520 .lvds_mask
= (1 << 1),
521 .hdmi_mask
= (1 << 1),
522 .cursor_needs_phys
= 0,
523 .sgx_offset
= MRST_SGX_OFFSET
,
525 .chip_setup
= mdfld_chip_setup
,
526 .crtc_helper
= &mdfld_helper_funcs
,
527 .crtc_funcs
= &psb_intel_crtc_funcs
,
529 .output_init
= mdfld_output_init
,
531 #ifdef CONFIG_BACKLIGHT_CLASS_DEVICE
532 .backlight_init
= mdfld_backlight_init
,
535 .save_regs
= mdfld_save_registers
,
536 .restore_regs
= mdfld_restore_registers
,
537 .save_crtc
= gma_crtc_save
,
538 .restore_crtc
= gma_crtc_restore
,
539 .power_down
= mdfld_power_down
,
540 .power_up
= mdfld_power_up
,