Linux Audio

Check our new training course

Loading...
v6.13.7
  1// SPDX-License-Identifier: GPL-2.0-only
  2/**************************************************************************
  3 * Copyright (c) 2011, Intel Corporation.
  4 * All Rights Reserved.
  5 *
  6 **************************************************************************/
  7
 
  8#include <linux/delay.h>
  9#include <linux/dmi.h>
 10#include <linux/module.h>
 11
 12#include <drm/drm.h>
 13
 14#include "intel_bios.h"
 15#include "mid_bios.h"
 16#include "psb_drv.h"
 17#include "psb_intel_reg.h"
 18#include "psb_reg.h"
 19
 20static int oaktrail_output_init(struct drm_device *dev)
 21{
 22	struct drm_psb_private *dev_priv = to_drm_psb_private(dev);
 23	if (dev_priv->iLVDS_enable)
 24		oaktrail_lvds_init(dev, &dev_priv->mode_dev);
 25	else
 26		dev_err(dev->dev, "DSI is not supported\n");
 27	if (dev_priv->hdmi_priv)
 28		oaktrail_hdmi_init(dev, &dev_priv->mode_dev);
 29
 30	psb_intel_sdvo_init(dev, SDVOB);
 31
 32	return 0;
 33}
 34
 35/*
 36 *	Provide the low level interfaces for the Moorestown backlight
 37 */
 38
 
 
 39#define MRST_BLC_MAX_PWM_REG_FREQ	    0xFFFF
 40#define BLC_PWM_PRECISION_FACTOR 100	/* 10000000 */
 41#define BLC_PWM_FREQ_CALC_CONSTANT 32
 42#define MHz 1000000
 43#define BLC_ADJUSTMENT_MAX 100
 44
 45static void oaktrail_set_brightness(struct drm_device *dev, int level)
 
 
 
 46{
 47	struct drm_psb_private *dev_priv = to_drm_psb_private(dev);
 
 
 48	u32 blc_pwm_ctl;
 49	u32 max_pwm_blc;
 50
 
 
 
 
 51	if (gma_power_begin(dev, 0)) {
 52		/* Calculate and set the brightness value */
 53		max_pwm_blc = REG_READ(BLC_PWM_CTL) >> 16;
 54		blc_pwm_ctl = level * max_pwm_blc / 100;
 55
 56		/* Adjust the backlight level with the percent in
 57		 * dev_priv->blc_adj1;
 58		 */
 59		blc_pwm_ctl = blc_pwm_ctl * dev_priv->blc_adj1;
 60		blc_pwm_ctl = blc_pwm_ctl / 100;
 61
 62		/* Adjust the backlight level with the percent in
 63		 * dev_priv->blc_adj2;
 64		 */
 65		blc_pwm_ctl = blc_pwm_ctl * dev_priv->blc_adj2;
 66		blc_pwm_ctl = blc_pwm_ctl / 100;
 67
 68		/* force PWM bit on */
 69		REG_WRITE(BLC_PWM_CTL2, (0x80000000 | REG_READ(BLC_PWM_CTL2)));
 70		REG_WRITE(BLC_PWM_CTL, (max_pwm_blc << 16) | blc_pwm_ctl);
 71		gma_power_end(dev);
 72	}
 
 
 73}
 74
 75static int oaktrail_backlight_init(struct drm_device *dev)
 
 
 
 
 
 
 
 
 76{
 77	struct drm_psb_private *dev_priv = to_drm_psb_private(dev);
 78	unsigned long core_clock;
 79	u16 bl_max_freq;
 80	uint32_t value;
 81	uint32_t blc_pwm_precision_factor;
 82
 83	dev_priv->blc_adj1 = BLC_ADJUSTMENT_MAX;
 84	dev_priv->blc_adj2 = BLC_ADJUSTMENT_MAX;
 85	bl_max_freq = 256;
 86	/* this needs to be set elsewhere */
 87	blc_pwm_precision_factor = BLC_PWM_PRECISION_FACTOR;
 88
 89	core_clock = dev_priv->core_freq;
 90
 91	value = (core_clock * MHz) / BLC_PWM_FREQ_CALC_CONSTANT;
 92	value *= blc_pwm_precision_factor;
 93	value /= bl_max_freq;
 94	value /= blc_pwm_precision_factor;
 95
 96	if (value > (unsigned long long)MRST_BLC_MAX_PWM_REG_FREQ)
 97			return -ERANGE;
 98
 99	if (gma_power_begin(dev, false)) {
100		REG_WRITE(BLC_PWM_CTL2, (0x80000000 | REG_READ(BLC_PWM_CTL2)));
101		REG_WRITE(BLC_PWM_CTL, value | (value << 16));
102		gma_power_end(dev);
103	}
 
 
 
 
 
 
 
104
105	oaktrail_set_brightness(dev, PSB_MAX_BRIGHTNESS);
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
106	return 0;
107}
108
 
 
109/*
110 *	Provide the Moorestown specific chip logic and low level methods
111 *	for power management
112 */
113
114/**
115 *	oaktrail_save_display_registers	-	save registers lost on suspend
116 *	@dev: our DRM device
117 *
118 *	Save the state we need in order to be able to restore the interface
119 *	upon resume from suspend
120 */
121static int oaktrail_save_display_registers(struct drm_device *dev)
122{
123	struct drm_psb_private *dev_priv = to_drm_psb_private(dev);
124	struct psb_save_area *regs = &dev_priv->regs;
125	struct psb_pipe *p = &regs->pipe[0];
126	int i;
127	u32 pp_stat;
128
129	/* Display arbitration control + watermarks */
130	regs->psb.saveDSPARB = PSB_RVDC32(DSPARB);
131	regs->psb.saveDSPFW1 = PSB_RVDC32(DSPFW1);
132	regs->psb.saveDSPFW2 = PSB_RVDC32(DSPFW2);
133	regs->psb.saveDSPFW3 = PSB_RVDC32(DSPFW3);
134	regs->psb.saveDSPFW4 = PSB_RVDC32(DSPFW4);
135	regs->psb.saveDSPFW5 = PSB_RVDC32(DSPFW5);
136	regs->psb.saveDSPFW6 = PSB_RVDC32(DSPFW6);
137	regs->psb.saveCHICKENBIT = PSB_RVDC32(DSPCHICKENBIT);
138
139	/* Pipe & plane A info */
140	p->conf = PSB_RVDC32(PIPEACONF);
141	p->src = PSB_RVDC32(PIPEASRC);
142	p->fp0 = PSB_RVDC32(MRST_FPA0);
143	p->fp1 = PSB_RVDC32(MRST_FPA1);
144	p->dpll = PSB_RVDC32(MRST_DPLL_A);
145	p->htotal = PSB_RVDC32(HTOTAL_A);
146	p->hblank = PSB_RVDC32(HBLANK_A);
147	p->hsync = PSB_RVDC32(HSYNC_A);
148	p->vtotal = PSB_RVDC32(VTOTAL_A);
149	p->vblank = PSB_RVDC32(VBLANK_A);
150	p->vsync = PSB_RVDC32(VSYNC_A);
151	regs->psb.saveBCLRPAT_A = PSB_RVDC32(BCLRPAT_A);
152	p->cntr = PSB_RVDC32(DSPACNTR);
153	p->stride = PSB_RVDC32(DSPASTRIDE);
154	p->addr = PSB_RVDC32(DSPABASE);
155	p->surf = PSB_RVDC32(DSPASURF);
156	p->linoff = PSB_RVDC32(DSPALINOFF);
157	p->tileoff = PSB_RVDC32(DSPATILEOFF);
158
159	/* Save cursor regs */
160	regs->psb.saveDSPACURSOR_CTRL = PSB_RVDC32(CURACNTR);
161	regs->psb.saveDSPACURSOR_BASE = PSB_RVDC32(CURABASE);
162	regs->psb.saveDSPACURSOR_POS = PSB_RVDC32(CURAPOS);
163
164	/* Save palette (gamma) */
165	for (i = 0; i < 256; i++)
166		p->palette[i] = PSB_RVDC32(PALETTE_A + (i << 2));
167
168	if (dev_priv->hdmi_priv)
169		oaktrail_hdmi_save(dev);
170
171	/* Save performance state */
172	regs->psb.savePERF_MODE = PSB_RVDC32(MRST_PERF_MODE);
173
174	/* LVDS state */
175	regs->psb.savePP_CONTROL = PSB_RVDC32(PP_CONTROL);
176	regs->psb.savePFIT_PGM_RATIOS = PSB_RVDC32(PFIT_PGM_RATIOS);
177	regs->psb.savePFIT_AUTO_RATIOS = PSB_RVDC32(PFIT_AUTO_RATIOS);
178	regs->saveBLC_PWM_CTL = PSB_RVDC32(BLC_PWM_CTL);
179	regs->saveBLC_PWM_CTL2 = PSB_RVDC32(BLC_PWM_CTL2);
180	regs->psb.saveLVDS = PSB_RVDC32(LVDS);
181	regs->psb.savePFIT_CONTROL = PSB_RVDC32(PFIT_CONTROL);
182	regs->psb.savePP_ON_DELAYS = PSB_RVDC32(LVDSPP_ON);
183	regs->psb.savePP_OFF_DELAYS = PSB_RVDC32(LVDSPP_OFF);
184	regs->psb.savePP_DIVISOR = PSB_RVDC32(PP_CYCLE);
185
186	/* HW overlay */
187	regs->psb.saveOV_OVADD = PSB_RVDC32(OV_OVADD);
188	regs->psb.saveOV_OGAMC0 = PSB_RVDC32(OV_OGAMC0);
189	regs->psb.saveOV_OGAMC1 = PSB_RVDC32(OV_OGAMC1);
190	regs->psb.saveOV_OGAMC2 = PSB_RVDC32(OV_OGAMC2);
191	regs->psb.saveOV_OGAMC3 = PSB_RVDC32(OV_OGAMC3);
192	regs->psb.saveOV_OGAMC4 = PSB_RVDC32(OV_OGAMC4);
193	regs->psb.saveOV_OGAMC5 = PSB_RVDC32(OV_OGAMC5);
194
195	/* DPST registers */
196	regs->psb.saveHISTOGRAM_INT_CONTROL_REG =
197					PSB_RVDC32(HISTOGRAM_INT_CONTROL);
198	regs->psb.saveHISTOGRAM_LOGIC_CONTROL_REG =
199					PSB_RVDC32(HISTOGRAM_LOGIC_CONTROL);
200	regs->psb.savePWM_CONTROL_LOGIC = PSB_RVDC32(PWM_CONTROL_LOGIC);
201
202	if (dev_priv->iLVDS_enable) {
203		/* Shut down the panel */
204		PSB_WVDC32(0, PP_CONTROL);
205
206		do {
207			pp_stat = PSB_RVDC32(PP_STATUS);
208		} while (pp_stat & 0x80000000);
209
210		/* Turn off the plane */
211		PSB_WVDC32(0x58000000, DSPACNTR);
212		/* Trigger the plane disable */
213		PSB_WVDC32(0, DSPASURF);
214
215		/* Wait ~4 ticks */
216		msleep(4);
217
218		/* Turn off pipe */
219		PSB_WVDC32(0x0, PIPEACONF);
220		/* Wait ~8 ticks */
221		msleep(8);
222
223		/* Turn off PLLs */
224		PSB_WVDC32(0, MRST_DPLL_A);
225	}
226	return 0;
227}
228
229/**
230 *	oaktrail_restore_display_registers	-	restore lost register state
231 *	@dev: our DRM device
232 *
233 *	Restore register state that was lost during suspend and resume.
234 */
235static int oaktrail_restore_display_registers(struct drm_device *dev)
236{
237	struct drm_psb_private *dev_priv = to_drm_psb_private(dev);
238	struct psb_save_area *regs = &dev_priv->regs;
239	struct psb_pipe *p = &regs->pipe[0];
240	u32 pp_stat;
241	int i;
242
243	/* Display arbitration + watermarks */
244	PSB_WVDC32(regs->psb.saveDSPARB, DSPARB);
245	PSB_WVDC32(regs->psb.saveDSPFW1, DSPFW1);
246	PSB_WVDC32(regs->psb.saveDSPFW2, DSPFW2);
247	PSB_WVDC32(regs->psb.saveDSPFW3, DSPFW3);
248	PSB_WVDC32(regs->psb.saveDSPFW4, DSPFW4);
249	PSB_WVDC32(regs->psb.saveDSPFW5, DSPFW5);
250	PSB_WVDC32(regs->psb.saveDSPFW6, DSPFW6);
251	PSB_WVDC32(regs->psb.saveCHICKENBIT, DSPCHICKENBIT);
252
253	/* Make sure VGA plane is off. it initializes to on after reset!*/
254	PSB_WVDC32(0x80000000, VGACNTRL);
255
256	/* set the plls */
257	PSB_WVDC32(p->fp0, MRST_FPA0);
258	PSB_WVDC32(p->fp1, MRST_FPA1);
259
260	/* Actually enable it */
261	PSB_WVDC32(p->dpll, MRST_DPLL_A);
262	udelay(150);
263
264	/* Restore mode */
265	PSB_WVDC32(p->htotal, HTOTAL_A);
266	PSB_WVDC32(p->hblank, HBLANK_A);
267	PSB_WVDC32(p->hsync, HSYNC_A);
268	PSB_WVDC32(p->vtotal, VTOTAL_A);
269	PSB_WVDC32(p->vblank, VBLANK_A);
270	PSB_WVDC32(p->vsync, VSYNC_A);
271	PSB_WVDC32(p->src, PIPEASRC);
272	PSB_WVDC32(regs->psb.saveBCLRPAT_A, BCLRPAT_A);
273
274	/* Restore performance mode*/
275	PSB_WVDC32(regs->psb.savePERF_MODE, MRST_PERF_MODE);
276
277	/* Enable the pipe*/
278	if (dev_priv->iLVDS_enable)
279		PSB_WVDC32(p->conf, PIPEACONF);
280
281	/* Set up the plane*/
282	PSB_WVDC32(p->linoff, DSPALINOFF);
283	PSB_WVDC32(p->stride, DSPASTRIDE);
284	PSB_WVDC32(p->tileoff, DSPATILEOFF);
285
286	/* Enable the plane */
287	PSB_WVDC32(p->cntr, DSPACNTR);
288	PSB_WVDC32(p->surf, DSPASURF);
289
290	/* Enable Cursor A */
291	PSB_WVDC32(regs->psb.saveDSPACURSOR_CTRL, CURACNTR);
292	PSB_WVDC32(regs->psb.saveDSPACURSOR_POS, CURAPOS);
293	PSB_WVDC32(regs->psb.saveDSPACURSOR_BASE, CURABASE);
294
295	/* Restore palette (gamma) */
296	for (i = 0; i < 256; i++)
297		PSB_WVDC32(p->palette[i], PALETTE_A + (i << 2));
298
299	if (dev_priv->hdmi_priv)
300		oaktrail_hdmi_restore(dev);
301
302	if (dev_priv->iLVDS_enable) {
303		PSB_WVDC32(regs->saveBLC_PWM_CTL2, BLC_PWM_CTL2);
304		PSB_WVDC32(regs->psb.saveLVDS, LVDS); /*port 61180h*/
305		PSB_WVDC32(regs->psb.savePFIT_CONTROL, PFIT_CONTROL);
306		PSB_WVDC32(regs->psb.savePFIT_PGM_RATIOS, PFIT_PGM_RATIOS);
307		PSB_WVDC32(regs->psb.savePFIT_AUTO_RATIOS, PFIT_AUTO_RATIOS);
308		PSB_WVDC32(regs->saveBLC_PWM_CTL, BLC_PWM_CTL);
309		PSB_WVDC32(regs->psb.savePP_ON_DELAYS, LVDSPP_ON);
310		PSB_WVDC32(regs->psb.savePP_OFF_DELAYS, LVDSPP_OFF);
311		PSB_WVDC32(regs->psb.savePP_DIVISOR, PP_CYCLE);
312		PSB_WVDC32(regs->psb.savePP_CONTROL, PP_CONTROL);
313	}
314
315	/* Wait for cycle delay */
316	do {
317		pp_stat = PSB_RVDC32(PP_STATUS);
318	} while (pp_stat & 0x08000000);
319
320	/* Wait for panel power up */
321	do {
322		pp_stat = PSB_RVDC32(PP_STATUS);
323	} while (pp_stat & 0x10000000);
324
325	/* Restore HW overlay */
326	PSB_WVDC32(regs->psb.saveOV_OVADD, OV_OVADD);
327	PSB_WVDC32(regs->psb.saveOV_OGAMC0, OV_OGAMC0);
328	PSB_WVDC32(regs->psb.saveOV_OGAMC1, OV_OGAMC1);
329	PSB_WVDC32(regs->psb.saveOV_OGAMC2, OV_OGAMC2);
330	PSB_WVDC32(regs->psb.saveOV_OGAMC3, OV_OGAMC3);
331	PSB_WVDC32(regs->psb.saveOV_OGAMC4, OV_OGAMC4);
332	PSB_WVDC32(regs->psb.saveOV_OGAMC5, OV_OGAMC5);
333
334	/* DPST registers */
335	PSB_WVDC32(regs->psb.saveHISTOGRAM_INT_CONTROL_REG,
336						HISTOGRAM_INT_CONTROL);
337	PSB_WVDC32(regs->psb.saveHISTOGRAM_LOGIC_CONTROL_REG,
338						HISTOGRAM_LOGIC_CONTROL);
339	PSB_WVDC32(regs->psb.savePWM_CONTROL_LOGIC, PWM_CONTROL_LOGIC);
340
341	return 0;
342}
343
344/**
345 *	oaktrail_power_down	-	power down the display island
346 *	@dev: our DRM device
347 *
348 *	Power down the display interface of our device
349 */
350static int oaktrail_power_down(struct drm_device *dev)
351{
352	struct drm_psb_private *dev_priv = to_drm_psb_private(dev);
353	u32 pwr_mask ;
354	u32 pwr_sts;
355
356	pwr_mask = PSB_PWRGT_DISPLAY_MASK;
357	outl(pwr_mask, dev_priv->ospm_base + PSB_PM_SSC);
358
359	while (true) {
360		pwr_sts = inl(dev_priv->ospm_base + PSB_PM_SSS);
361		if ((pwr_sts & pwr_mask) == pwr_mask)
362			break;
363		else
364			udelay(10);
365	}
366	return 0;
367}
368
369/*
370 * oaktrail_power_up
371 *
372 * Restore power to the specified island(s) (powergating)
373 */
374static int oaktrail_power_up(struct drm_device *dev)
375{
376	struct drm_psb_private *dev_priv = to_drm_psb_private(dev);
377	u32 pwr_mask = PSB_PWRGT_DISPLAY_MASK;
378	u32 pwr_sts, pwr_cnt;
379
380	pwr_cnt = inl(dev_priv->ospm_base + PSB_PM_SSC);
381	pwr_cnt &= ~pwr_mask;
382	outl(pwr_cnt, (dev_priv->ospm_base + PSB_PM_SSC));
383
384	while (true) {
385		pwr_sts = inl(dev_priv->ospm_base + PSB_PM_SSS);
386		if ((pwr_sts & pwr_mask) == 0)
387			break;
388		else
389			udelay(10);
390	}
391	return 0;
392}
393
394/* Oaktrail */
395static const struct psb_offset oaktrail_regmap[2] = {
396	{
397		.fp0 = MRST_FPA0,
398		.fp1 = MRST_FPA1,
399		.cntr = DSPACNTR,
400		.conf = PIPEACONF,
401		.src = PIPEASRC,
402		.dpll = MRST_DPLL_A,
403		.htotal = HTOTAL_A,
404		.hblank = HBLANK_A,
405		.hsync = HSYNC_A,
406		.vtotal = VTOTAL_A,
407		.vblank = VBLANK_A,
408		.vsync = VSYNC_A,
409		.stride = DSPASTRIDE,
410		.size = DSPASIZE,
411		.pos = DSPAPOS,
412		.surf = DSPASURF,
413		.addr = MRST_DSPABASE,
414		.base = MRST_DSPABASE,
415		.status = PIPEASTAT,
416		.linoff = DSPALINOFF,
417		.tileoff = DSPATILEOFF,
418		.palette = PALETTE_A,
419	},
420	{
421		.fp0 = FPB0,
422		.fp1 = FPB1,
423		.cntr = DSPBCNTR,
424		.conf = PIPEBCONF,
425		.src = PIPEBSRC,
426		.dpll = DPLL_B,
427		.htotal = HTOTAL_B,
428		.hblank = HBLANK_B,
429		.hsync = HSYNC_B,
430		.vtotal = VTOTAL_B,
431		.vblank = VBLANK_B,
432		.vsync = VSYNC_B,
433		.stride = DSPBSTRIDE,
434		.size = DSPBSIZE,
435		.pos = DSPBPOS,
436		.surf = DSPBSURF,
437		.addr = DSPBBASE,
438		.base = DSPBBASE,
439		.status = PIPEBSTAT,
440		.linoff = DSPBLINOFF,
441		.tileoff = DSPBTILEOFF,
442		.palette = PALETTE_B,
443	},
444};
445
446static int oaktrail_chip_setup(struct drm_device *dev)
447{
448	struct drm_psb_private *dev_priv = to_drm_psb_private(dev);
 
449	int ret;
450
451	dev_priv->use_msi = true;
 
 
452	dev_priv->regmap = oaktrail_regmap;
453
454	ret = mid_chip_setup(dev);
455	if (ret < 0)
456		return ret;
457	if (!dev_priv->has_gct) {
458		/* Now pull the BIOS data */
459		psb_intel_opregion_init(dev);
460		psb_intel_init_bios(dev);
461	}
462	gma_intel_setup_gmbus(dev);
463	oaktrail_hdmi_setup(dev);
464	return 0;
465}
466
467static void oaktrail_teardown(struct drm_device *dev)
468{
469	struct drm_psb_private *dev_priv = to_drm_psb_private(dev);
470
471	gma_intel_teardown_gmbus(dev);
472	oaktrail_hdmi_teardown(dev);
473	if (!dev_priv->has_gct)
474		psb_intel_destroy_bios(dev);
475}
476
477const struct psb_ops oaktrail_chip_ops = {
478	.name = "Oaktrail",
479	.pipes = 2,
480	.crtcs = 2,
481	.hdmi_mask = (1 << 1),
482	.lvds_mask = (1 << 0),
483	.sdvo_mask = (1 << 1),
484	.cursor_needs_phys = 0,
485	.sgx_offset = MRST_SGX_OFFSET,
486
487	.chip_setup = oaktrail_chip_setup,
488	.chip_teardown = oaktrail_teardown,
489	.crtc_helper = &oaktrail_helper_funcs,
 
490
491	.output_init = oaktrail_output_init,
492
 
493	.backlight_init = oaktrail_backlight_init,
494	.backlight_set = oaktrail_set_brightness,
495	.backlight_name = "oaktrail-bl",
496
497	.save_regs = oaktrail_save_display_registers,
498	.restore_regs = oaktrail_restore_display_registers,
499	.save_crtc = gma_crtc_save,
500	.restore_crtc = gma_crtc_restore,
501	.power_down = oaktrail_power_down,
502	.power_up = oaktrail_power_up,
503
504	.i2c_bus = 1,
505};
v5.14.15
  1// SPDX-License-Identifier: GPL-2.0-only
  2/**************************************************************************
  3 * Copyright (c) 2011, Intel Corporation.
  4 * All Rights Reserved.
  5 *
  6 **************************************************************************/
  7
  8#include <linux/backlight.h>
  9#include <linux/delay.h>
 10#include <linux/dmi.h>
 11#include <linux/module.h>
 12
 13#include <drm/drm.h>
 14
 15#include "intel_bios.h"
 16#include "mid_bios.h"
 17#include "psb_drv.h"
 18#include "psb_intel_reg.h"
 19#include "psb_reg.h"
 20
 21static int oaktrail_output_init(struct drm_device *dev)
 22{
 23	struct drm_psb_private *dev_priv = dev->dev_private;
 24	if (dev_priv->iLVDS_enable)
 25		oaktrail_lvds_init(dev, &dev_priv->mode_dev);
 26	else
 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);
 30
 31	psb_intel_sdvo_init(dev, SDVOB);
 32
 33	return 0;
 34}
 35
 36/*
 37 *	Provide the low level interfaces for the Moorestown backlight
 38 */
 39
 40#ifdef CONFIG_BACKLIGHT_CLASS_DEVICE
 41
 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
 45#define MHz 1000000
 46#define BLC_ADJUSTMENT_MAX 100
 47
 48static struct backlight_device *oaktrail_backlight_device;
 49static int oaktrail_brightness;
 50
 51static int oaktrail_set_brightness(struct backlight_device *bd)
 52{
 53	struct drm_device *dev = bl_get_data(oaktrail_backlight_device);
 54	struct drm_psb_private *dev_priv = dev->dev_private;
 55	int level = bd->props.brightness;
 56	u32 blc_pwm_ctl;
 57	u32 max_pwm_blc;
 58
 59	/* Percentage 1-100% being valid */
 60	if (level < 1)
 61		level = 1;
 62
 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;
 67
 68		/* Adjust the backlight level with the percent in
 69		 * dev_priv->blc_adj1;
 70		 */
 71		blc_pwm_ctl = blc_pwm_ctl * dev_priv->blc_adj1;
 72		blc_pwm_ctl = blc_pwm_ctl / 100;
 73
 74		/* Adjust the backlight level with the percent in
 75		 * dev_priv->blc_adj2;
 76		 */
 77		blc_pwm_ctl = blc_pwm_ctl * dev_priv->blc_adj2;
 78		blc_pwm_ctl = blc_pwm_ctl / 100;
 79
 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);
 83		gma_power_end(dev);
 84	}
 85	oaktrail_brightness = level;
 86	return 0;
 87}
 88
 89static int oaktrail_get_brightness(struct backlight_device *bd)
 90{
 91	/* return locally cached var instead of HW read (due to DPST etc.) */
 92	/* FIXME: ideally return actual value in case firmware fiddled with
 93	   it */
 94	return oaktrail_brightness;
 95}
 96
 97static int device_backlight_init(struct drm_device *dev)
 98{
 99	struct drm_psb_private *dev_priv = dev->dev_private;
100	unsigned long core_clock;
101	u16 bl_max_freq;
102	uint32_t value;
103	uint32_t blc_pwm_precision_factor;
104
105	dev_priv->blc_adj1 = BLC_ADJUSTMENT_MAX;
106	dev_priv->blc_adj2 = BLC_ADJUSTMENT_MAX;
107	bl_max_freq = 256;
108	/* this needs to be set elsewhere */
109	blc_pwm_precision_factor = BLC_PWM_PRECISION_FACTOR;
110
111	core_clock = dev_priv->core_freq;
112
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;
117
118	if (value > (unsigned long long)MRST_BLC_MAX_PWM_REG_FREQ)
119			return -ERANGE;
120
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));
124		gma_power_end(dev);
125	}
126	return 0;
127}
128
129static const struct backlight_ops oaktrail_ops = {
130	.get_brightness = oaktrail_get_brightness,
131	.update_status  = oaktrail_set_brightness,
132};
133
134static int oaktrail_backlight_init(struct drm_device *dev)
135{
136	struct drm_psb_private *dev_priv = dev->dev_private;
137	int ret;
138	struct backlight_properties props;
139
140	memset(&props, 0, sizeof(struct backlight_properties));
141	props.max_brightness = 100;
142	props.type = BACKLIGHT_PLATFORM;
143
144	oaktrail_backlight_device = backlight_device_register("oaktrail-bl",
145				NULL, (void *)dev, &oaktrail_ops, &props);
146
147	if (IS_ERR(oaktrail_backlight_device))
148		return PTR_ERR(oaktrail_backlight_device);
149
150	ret = device_backlight_init(dev);
151	if (ret < 0) {
152		backlight_device_unregister(oaktrail_backlight_device);
153		return ret;
154	}
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;
159	return 0;
160}
161
162#endif
163
164/*
165 *	Provide the Moorestown specific chip logic and low level methods
166 *	for power management
167 */
168
169/**
170 *	oaktrail_save_display_registers	-	save registers lost on suspend
171 *	@dev: our DRM device
172 *
173 *	Save the state we need in order to be able to restore the interface
174 *	upon resume from suspend
175 */
176static int oaktrail_save_display_registers(struct drm_device *dev)
177{
178	struct drm_psb_private *dev_priv = dev->dev_private;
179	struct psb_save_area *regs = &dev_priv->regs;
180	struct psb_pipe *p = &regs->pipe[0];
181	int i;
182	u32 pp_stat;
183
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);
193
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);
213
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);
218
219	/* Save palette (gamma) */
220	for (i = 0; i < 256; i++)
221		p->palette[i] = PSB_RVDC32(PALETTE_A + (i << 2));
222
223	if (dev_priv->hdmi_priv)
224		oaktrail_hdmi_save(dev);
225
226	/* Save performance state */
227	regs->psb.savePERF_MODE = PSB_RVDC32(MRST_PERF_MODE);
228
229	/* LVDS state */
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);
240
241	/* HW overlay */
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);
249
250	/* DPST registers */
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);
256
257	if (dev_priv->iLVDS_enable) {
258		/* Shut down the panel */
259		PSB_WVDC32(0, PP_CONTROL);
260
261		do {
262			pp_stat = PSB_RVDC32(PP_STATUS);
263		} while (pp_stat & 0x80000000);
264
265		/* Turn off the plane */
266		PSB_WVDC32(0x58000000, DSPACNTR);
267		/* Trigger the plane disable */
268		PSB_WVDC32(0, DSPASURF);
269
270		/* Wait ~4 ticks */
271		msleep(4);
272
273		/* Turn off pipe */
274		PSB_WVDC32(0x0, PIPEACONF);
275		/* Wait ~8 ticks */
276		msleep(8);
277
278		/* Turn off PLLs */
279		PSB_WVDC32(0, MRST_DPLL_A);
280	}
281	return 0;
282}
283
284/**
285 *	oaktrail_restore_display_registers	-	restore lost register state
286 *	@dev: our DRM device
287 *
288 *	Restore register state that was lost during suspend and resume.
289 */
290static int oaktrail_restore_display_registers(struct drm_device *dev)
291{
292	struct drm_psb_private *dev_priv = dev->dev_private;
293	struct psb_save_area *regs = &dev_priv->regs;
294	struct psb_pipe *p = &regs->pipe[0];
295	u32 pp_stat;
296	int i;
297
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);
307
308	/* Make sure VGA plane is off. it initializes to on after reset!*/
309	PSB_WVDC32(0x80000000, VGACNTRL);
310
311	/* set the plls */
312	PSB_WVDC32(p->fp0, MRST_FPA0);
313	PSB_WVDC32(p->fp1, MRST_FPA1);
314
315	/* Actually enable it */
316	PSB_WVDC32(p->dpll, MRST_DPLL_A);
317	udelay(150);
318
319	/* Restore mode */
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);
328
329	/* Restore performance mode*/
330	PSB_WVDC32(regs->psb.savePERF_MODE, MRST_PERF_MODE);
331
332	/* Enable the pipe*/
333	if (dev_priv->iLVDS_enable)
334		PSB_WVDC32(p->conf, PIPEACONF);
335
336	/* Set up the plane*/
337	PSB_WVDC32(p->linoff, DSPALINOFF);
338	PSB_WVDC32(p->stride, DSPASTRIDE);
339	PSB_WVDC32(p->tileoff, DSPATILEOFF);
340
341	/* Enable the plane */
342	PSB_WVDC32(p->cntr, DSPACNTR);
343	PSB_WVDC32(p->surf, DSPASURF);
344
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);
349
350	/* Restore palette (gamma) */
351	for (i = 0; i < 256; i++)
352		PSB_WVDC32(p->palette[i], PALETTE_A + (i << 2));
353
354	if (dev_priv->hdmi_priv)
355		oaktrail_hdmi_restore(dev);
356
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);
368	}
369
370	/* Wait for cycle delay */
371	do {
372		pp_stat = PSB_RVDC32(PP_STATUS);
373	} while (pp_stat & 0x08000000);
374
375	/* Wait for panel power up */
376	do {
377		pp_stat = PSB_RVDC32(PP_STATUS);
378	} while (pp_stat & 0x10000000);
379
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);
388
389	/* DPST registers */
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);
395
396	return 0;
397}
398
399/**
400 *	oaktrail_power_down	-	power down the display island
401 *	@dev: our DRM device
402 *
403 *	Power down the display interface of our device
404 */
405static int oaktrail_power_down(struct drm_device *dev)
406{
407	struct drm_psb_private *dev_priv = dev->dev_private;
408	u32 pwr_mask ;
409	u32 pwr_sts;
410
411	pwr_mask = PSB_PWRGT_DISPLAY_MASK;
412	outl(pwr_mask, dev_priv->ospm_base + PSB_PM_SSC);
413
414	while (true) {
415		pwr_sts = inl(dev_priv->ospm_base + PSB_PM_SSS);
416		if ((pwr_sts & pwr_mask) == pwr_mask)
417			break;
418		else
419			udelay(10);
420	}
421	return 0;
422}
423
424/*
425 * oaktrail_power_up
426 *
427 * Restore power to the specified island(s) (powergating)
428 */
429static int oaktrail_power_up(struct drm_device *dev)
430{
431	struct drm_psb_private *dev_priv = dev->dev_private;
432	u32 pwr_mask = PSB_PWRGT_DISPLAY_MASK;
433	u32 pwr_sts, pwr_cnt;
434
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));
438
439	while (true) {
440		pwr_sts = inl(dev_priv->ospm_base + PSB_PM_SSS);
441		if ((pwr_sts & pwr_mask) == 0)
442			break;
443		else
444			udelay(10);
445	}
446	return 0;
447}
448
449/* Oaktrail */
450static const struct psb_offset oaktrail_regmap[2] = {
451	{
452		.fp0 = MRST_FPA0,
453		.fp1 = MRST_FPA1,
454		.cntr = DSPACNTR,
455		.conf = PIPEACONF,
456		.src = PIPEASRC,
457		.dpll = MRST_DPLL_A,
458		.htotal = HTOTAL_A,
459		.hblank = HBLANK_A,
460		.hsync = HSYNC_A,
461		.vtotal = VTOTAL_A,
462		.vblank = VBLANK_A,
463		.vsync = VSYNC_A,
464		.stride = DSPASTRIDE,
465		.size = DSPASIZE,
466		.pos = DSPAPOS,
467		.surf = DSPASURF,
468		.addr = MRST_DSPABASE,
469		.base = MRST_DSPABASE,
470		.status = PIPEASTAT,
471		.linoff = DSPALINOFF,
472		.tileoff = DSPATILEOFF,
473		.palette = PALETTE_A,
474	},
475	{
476		.fp0 = FPB0,
477		.fp1 = FPB1,
478		.cntr = DSPBCNTR,
479		.conf = PIPEBCONF,
480		.src = PIPEBSRC,
481		.dpll = DPLL_B,
482		.htotal = HTOTAL_B,
483		.hblank = HBLANK_B,
484		.hsync = HSYNC_B,
485		.vtotal = VTOTAL_B,
486		.vblank = VBLANK_B,
487		.vsync = VSYNC_B,
488		.stride = DSPBSTRIDE,
489		.size = DSPBSIZE,
490		.pos = DSPBPOS,
491		.surf = DSPBSURF,
492		.addr = DSPBBASE,
493		.base = DSPBBASE,
494		.status = PIPEBSTAT,
495		.linoff = DSPBLINOFF,
496		.tileoff = DSPBTILEOFF,
497		.palette = PALETTE_B,
498	},
499};
500
501static int oaktrail_chip_setup(struct drm_device *dev)
502{
503	struct drm_psb_private *dev_priv = dev->dev_private;
504	struct pci_dev *pdev = to_pci_dev(dev->dev);
505	int ret;
506
507	if (pci_enable_msi(pdev))
508		dev_warn(dev->dev, "Enabling MSI failed!\n");
509
510	dev_priv->regmap = oaktrail_regmap;
511
512	ret = mid_chip_setup(dev);
513	if (ret < 0)
514		return ret;
515	if (!dev_priv->has_gct) {
516		/* Now pull the BIOS data */
517		psb_intel_opregion_init(dev);
518		psb_intel_init_bios(dev);
519	}
520	gma_intel_setup_gmbus(dev);
521	oaktrail_hdmi_setup(dev);
522	return 0;
523}
524
525static void oaktrail_teardown(struct drm_device *dev)
526{
527	struct drm_psb_private *dev_priv = dev->dev_private;
528
529	gma_intel_teardown_gmbus(dev);
530	oaktrail_hdmi_teardown(dev);
531	if (!dev_priv->has_gct)
532		psb_intel_destroy_bios(dev);
533}
534
535const struct psb_ops oaktrail_chip_ops = {
536	.name = "Oaktrail",
537	.pipes = 2,
538	.crtcs = 2,
539	.hdmi_mask = (1 << 1),
540	.lvds_mask = (1 << 0),
541	.sdvo_mask = (1 << 1),
542	.cursor_needs_phys = 0,
543	.sgx_offset = MRST_SGX_OFFSET,
544
545	.chip_setup = oaktrail_chip_setup,
546	.chip_teardown = oaktrail_teardown,
547	.crtc_helper = &oaktrail_helper_funcs,
548	.crtc_funcs = &gma_intel_crtc_funcs,
549
550	.output_init = oaktrail_output_init,
551
552#ifdef CONFIG_BACKLIGHT_CLASS_DEVICE
553	.backlight_init = oaktrail_backlight_init,
554#endif
 
555
556	.save_regs = oaktrail_save_display_registers,
557	.restore_regs = oaktrail_restore_display_registers,
558	.save_crtc = gma_crtc_save,
559	.restore_crtc = gma_crtc_restore,
560	.power_down = oaktrail_power_down,
561	.power_up = oaktrail_power_up,
562
563	.i2c_bus = 1,
564};