brintos

brintos / linux-shallow public Read only

0
0
Text · 13.4 KiB · 2531959 Raw
506 lines · c
1// SPDX-License-Identifier: GPL-2.0-only2/**************************************************************************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	else26		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 backlight37 */38 39#define MRST_BLC_MAX_PWM_REG_FREQ	    0xFFFF40#define BLC_PWM_PRECISION_FACTOR 100	/* 10000000 */41#define BLC_PWM_FREQ_CALC_CONSTANT 3242#define MHz 100000043#define BLC_ADJUSTMENT_MAX 10044 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 in57		 * 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 in63		 * 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 methods111 *	for power management112 */113 114/**115 *	oaktrail_save_display_registers	-	save registers lost on suspend116 *	@dev: our DRM device117 *118 *	Save the state we need in order to be able to restore the interface119 *	upon resume from suspend120 */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 state231 *	@dev: our DRM device232 *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 island346 *	@dev: our DRM device347 *348 *	Power down the display interface of our device349 */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		else364			udelay(10);365	}366	return 0;367}368 369/*370 * oaktrail_power_up371 *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		else389			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};506