[go: nahoru, domu]

psb_device.c revision bc794829141f28e14fe7d0e07e35870bd9aee78c
189c78134cc54dff016c83367912eb055637fa50cAlan Cox/**************************************************************************
289c78134cc54dff016c83367912eb055637fa50cAlan Cox * Copyright (c) 2011, Intel Corporation.
389c78134cc54dff016c83367912eb055637fa50cAlan Cox * All Rights Reserved.
489c78134cc54dff016c83367912eb055637fa50cAlan Cox *
589c78134cc54dff016c83367912eb055637fa50cAlan Cox * This program is free software; you can redistribute it and/or modify it
689c78134cc54dff016c83367912eb055637fa50cAlan Cox * under the terms and conditions of the GNU General Public License,
789c78134cc54dff016c83367912eb055637fa50cAlan Cox * version 2, as published by the Free Software Foundation.
889c78134cc54dff016c83367912eb055637fa50cAlan Cox *
989c78134cc54dff016c83367912eb055637fa50cAlan Cox * This program is distributed in the hope it will be useful, but WITHOUT
1089c78134cc54dff016c83367912eb055637fa50cAlan Cox * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
1189c78134cc54dff016c83367912eb055637fa50cAlan Cox * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License for
1289c78134cc54dff016c83367912eb055637fa50cAlan Cox * more details.
1389c78134cc54dff016c83367912eb055637fa50cAlan Cox *
1489c78134cc54dff016c83367912eb055637fa50cAlan Cox * You should have received a copy of the GNU General Public License along with
1589c78134cc54dff016c83367912eb055637fa50cAlan Cox * this program; if not, write to the Free Software Foundation, Inc.,
1689c78134cc54dff016c83367912eb055637fa50cAlan Cox * 51 Franklin St - Fifth Floor, Boston, MA 02110-1301 USA.
1789c78134cc54dff016c83367912eb055637fa50cAlan Cox *
1889c78134cc54dff016c83367912eb055637fa50cAlan Cox **************************************************************************/
1989c78134cc54dff016c83367912eb055637fa50cAlan Cox
2089c78134cc54dff016c83367912eb055637fa50cAlan Cox#include <linux/backlight.h>
2189c78134cc54dff016c83367912eb055637fa50cAlan Cox#include <drm/drmP.h>
2289c78134cc54dff016c83367912eb055637fa50cAlan Cox#include <drm/drm.h>
23838fa588a29331da012876623c3bc170d7d647c2Alan Cox#include "gma_drm.h"
2489c78134cc54dff016c83367912eb055637fa50cAlan Cox#include "psb_drv.h"
2589c78134cc54dff016c83367912eb055637fa50cAlan Cox#include "psb_reg.h"
2689c78134cc54dff016c83367912eb055637fa50cAlan Cox#include "psb_intel_reg.h"
2789c78134cc54dff016c83367912eb055637fa50cAlan Cox#include "intel_bios.h"
2889c78134cc54dff016c83367912eb055637fa50cAlan Cox
2989c78134cc54dff016c83367912eb055637fa50cAlan Cox
3089c78134cc54dff016c83367912eb055637fa50cAlan Coxstatic int psb_output_init(struct drm_device *dev)
3189c78134cc54dff016c83367912eb055637fa50cAlan Cox{
3289c78134cc54dff016c83367912eb055637fa50cAlan Cox	struct drm_psb_private *dev_priv = dev->dev_private;
3389c78134cc54dff016c83367912eb055637fa50cAlan Cox	psb_intel_lvds_init(dev, &dev_priv->mode_dev);
3489c78134cc54dff016c83367912eb055637fa50cAlan Cox	psb_intel_sdvo_init(dev, SDVOB);
3589c78134cc54dff016c83367912eb055637fa50cAlan Cox	return 0;
3689c78134cc54dff016c83367912eb055637fa50cAlan Cox}
3789c78134cc54dff016c83367912eb055637fa50cAlan Cox
3889c78134cc54dff016c83367912eb055637fa50cAlan Cox#ifdef CONFIG_BACKLIGHT_CLASS_DEVICE
3989c78134cc54dff016c83367912eb055637fa50cAlan Cox
4089c78134cc54dff016c83367912eb055637fa50cAlan Cox/*
4189c78134cc54dff016c83367912eb055637fa50cAlan Cox *	Poulsbo Backlight Interfaces
4289c78134cc54dff016c83367912eb055637fa50cAlan Cox */
4389c78134cc54dff016c83367912eb055637fa50cAlan Cox
4489c78134cc54dff016c83367912eb055637fa50cAlan Cox#define BLC_PWM_PRECISION_FACTOR 100	/* 10000000 */
4589c78134cc54dff016c83367912eb055637fa50cAlan Cox#define BLC_PWM_FREQ_CALC_CONSTANT 32
4689c78134cc54dff016c83367912eb055637fa50cAlan Cox#define MHz 1000000
4789c78134cc54dff016c83367912eb055637fa50cAlan Cox
4889c78134cc54dff016c83367912eb055637fa50cAlan Cox#define PSB_BLC_PWM_PRECISION_FACTOR    10
4989c78134cc54dff016c83367912eb055637fa50cAlan Cox#define PSB_BLC_MAX_PWM_REG_FREQ        0xFFFE
5089c78134cc54dff016c83367912eb055637fa50cAlan Cox#define PSB_BLC_MIN_PWM_REG_FREQ        0x2
5189c78134cc54dff016c83367912eb055637fa50cAlan Cox
5289c78134cc54dff016c83367912eb055637fa50cAlan Cox#define PSB_BACKLIGHT_PWM_POLARITY_BIT_CLEAR (0xFFFE)
5389c78134cc54dff016c83367912eb055637fa50cAlan Cox#define PSB_BACKLIGHT_PWM_CTL_SHIFT	(16)
5489c78134cc54dff016c83367912eb055637fa50cAlan Cox
5589c78134cc54dff016c83367912eb055637fa50cAlan Coxstatic int psb_brightness;
5689c78134cc54dff016c83367912eb055637fa50cAlan Coxstatic struct backlight_device *psb_backlight_device;
5789c78134cc54dff016c83367912eb055637fa50cAlan Cox
5889c78134cc54dff016c83367912eb055637fa50cAlan Coxstatic int psb_get_brightness(struct backlight_device *bd)
5989c78134cc54dff016c83367912eb055637fa50cAlan Cox{
6089c78134cc54dff016c83367912eb055637fa50cAlan Cox	/* return locally cached var instead of HW read (due to DPST etc.) */
6189c78134cc54dff016c83367912eb055637fa50cAlan Cox	/* FIXME: ideally return actual value in case firmware fiddled with
6289c78134cc54dff016c83367912eb055637fa50cAlan Cox	   it */
6389c78134cc54dff016c83367912eb055637fa50cAlan Cox	return psb_brightness;
6489c78134cc54dff016c83367912eb055637fa50cAlan Cox}
6589c78134cc54dff016c83367912eb055637fa50cAlan Cox
6689c78134cc54dff016c83367912eb055637fa50cAlan Cox
6789c78134cc54dff016c83367912eb055637fa50cAlan Coxstatic int psb_backlight_setup(struct drm_device *dev)
6889c78134cc54dff016c83367912eb055637fa50cAlan Cox{
6989c78134cc54dff016c83367912eb055637fa50cAlan Cox	struct drm_psb_private *dev_priv = dev->dev_private;
7089c78134cc54dff016c83367912eb055637fa50cAlan Cox	unsigned long core_clock;
7189c78134cc54dff016c83367912eb055637fa50cAlan Cox	/* u32 bl_max_freq; */
7289c78134cc54dff016c83367912eb055637fa50cAlan Cox	/* unsigned long value; */
7389c78134cc54dff016c83367912eb055637fa50cAlan Cox	u16 bl_max_freq;
7489c78134cc54dff016c83367912eb055637fa50cAlan Cox	uint32_t value;
7589c78134cc54dff016c83367912eb055637fa50cAlan Cox	uint32_t blc_pwm_precision_factor;
7689c78134cc54dff016c83367912eb055637fa50cAlan Cox
7789c78134cc54dff016c83367912eb055637fa50cAlan Cox	/* get bl_max_freq and pol from dev_priv*/
7889c78134cc54dff016c83367912eb055637fa50cAlan Cox	if (!dev_priv->lvds_bl) {
7989c78134cc54dff016c83367912eb055637fa50cAlan Cox		dev_err(dev->dev, "Has no valid LVDS backlight info\n");
8089c78134cc54dff016c83367912eb055637fa50cAlan Cox		return -ENOENT;
8189c78134cc54dff016c83367912eb055637fa50cAlan Cox	}
8289c78134cc54dff016c83367912eb055637fa50cAlan Cox	bl_max_freq = dev_priv->lvds_bl->freq;
8389c78134cc54dff016c83367912eb055637fa50cAlan Cox	blc_pwm_precision_factor = PSB_BLC_PWM_PRECISION_FACTOR;
8489c78134cc54dff016c83367912eb055637fa50cAlan Cox
8589c78134cc54dff016c83367912eb055637fa50cAlan Cox	core_clock = dev_priv->core_freq;
8689c78134cc54dff016c83367912eb055637fa50cAlan Cox
8789c78134cc54dff016c83367912eb055637fa50cAlan Cox	value = (core_clock * MHz) / BLC_PWM_FREQ_CALC_CONSTANT;
8889c78134cc54dff016c83367912eb055637fa50cAlan Cox	value *= blc_pwm_precision_factor;
8989c78134cc54dff016c83367912eb055637fa50cAlan Cox	value /= bl_max_freq;
9089c78134cc54dff016c83367912eb055637fa50cAlan Cox	value /= blc_pwm_precision_factor;
9189c78134cc54dff016c83367912eb055637fa50cAlan Cox
9289c78134cc54dff016c83367912eb055637fa50cAlan Cox	if (value > (unsigned long long)PSB_BLC_MAX_PWM_REG_FREQ ||
9389c78134cc54dff016c83367912eb055637fa50cAlan Cox		 value < (unsigned long long)PSB_BLC_MIN_PWM_REG_FREQ)
9489c78134cc54dff016c83367912eb055637fa50cAlan Cox				return -ERANGE;
9589c78134cc54dff016c83367912eb055637fa50cAlan Cox	else {
9689c78134cc54dff016c83367912eb055637fa50cAlan Cox		value &= PSB_BACKLIGHT_PWM_POLARITY_BIT_CLEAR;
9789c78134cc54dff016c83367912eb055637fa50cAlan Cox		REG_WRITE(BLC_PWM_CTL,
9889c78134cc54dff016c83367912eb055637fa50cAlan Cox			(value << PSB_BACKLIGHT_PWM_CTL_SHIFT) | (value));
9989c78134cc54dff016c83367912eb055637fa50cAlan Cox	}
10089c78134cc54dff016c83367912eb055637fa50cAlan Cox	return 0;
10189c78134cc54dff016c83367912eb055637fa50cAlan Cox}
10289c78134cc54dff016c83367912eb055637fa50cAlan Cox
10389c78134cc54dff016c83367912eb055637fa50cAlan Coxstatic int psb_set_brightness(struct backlight_device *bd)
10489c78134cc54dff016c83367912eb055637fa50cAlan Cox{
10589c78134cc54dff016c83367912eb055637fa50cAlan Cox	struct drm_device *dev = bl_get_data(psb_backlight_device);
10689c78134cc54dff016c83367912eb055637fa50cAlan Cox	int level = bd->props.brightness;
10789c78134cc54dff016c83367912eb055637fa50cAlan Cox
10889c78134cc54dff016c83367912eb055637fa50cAlan Cox	/* Percentage 1-100% being valid */
10989c78134cc54dff016c83367912eb055637fa50cAlan Cox	if (level < 1)
11089c78134cc54dff016c83367912eb055637fa50cAlan Cox		level = 1;
11189c78134cc54dff016c83367912eb055637fa50cAlan Cox
11289c78134cc54dff016c83367912eb055637fa50cAlan Cox	psb_intel_lvds_set_brightness(dev, level);
11389c78134cc54dff016c83367912eb055637fa50cAlan Cox	psb_brightness = level;
11489c78134cc54dff016c83367912eb055637fa50cAlan Cox	return 0;
11589c78134cc54dff016c83367912eb055637fa50cAlan Cox}
11689c78134cc54dff016c83367912eb055637fa50cAlan Cox
11789c78134cc54dff016c83367912eb055637fa50cAlan Coxstatic const struct backlight_ops psb_ops = {
11889c78134cc54dff016c83367912eb055637fa50cAlan Cox	.get_brightness = psb_get_brightness,
11989c78134cc54dff016c83367912eb055637fa50cAlan Cox	.update_status  = psb_set_brightness,
12089c78134cc54dff016c83367912eb055637fa50cAlan Cox};
12189c78134cc54dff016c83367912eb055637fa50cAlan Cox
12289c78134cc54dff016c83367912eb055637fa50cAlan Coxstatic int psb_backlight_init(struct drm_device *dev)
12389c78134cc54dff016c83367912eb055637fa50cAlan Cox{
12489c78134cc54dff016c83367912eb055637fa50cAlan Cox	struct drm_psb_private *dev_priv = dev->dev_private;
12589c78134cc54dff016c83367912eb055637fa50cAlan Cox	int ret;
12689c78134cc54dff016c83367912eb055637fa50cAlan Cox	struct backlight_properties props;
12789c78134cc54dff016c83367912eb055637fa50cAlan Cox
12889c78134cc54dff016c83367912eb055637fa50cAlan Cox	memset(&props, 0, sizeof(struct backlight_properties));
12989c78134cc54dff016c83367912eb055637fa50cAlan Cox	props.max_brightness = 100;
13089c78134cc54dff016c83367912eb055637fa50cAlan Cox	props.type = BACKLIGHT_PLATFORM;
13189c78134cc54dff016c83367912eb055637fa50cAlan Cox
13289c78134cc54dff016c83367912eb055637fa50cAlan Cox	psb_backlight_device = backlight_device_register("psb-bl",
13389c78134cc54dff016c83367912eb055637fa50cAlan Cox					NULL, (void *)dev, &psb_ops, &props);
13489c78134cc54dff016c83367912eb055637fa50cAlan Cox	if (IS_ERR(psb_backlight_device))
13589c78134cc54dff016c83367912eb055637fa50cAlan Cox		return PTR_ERR(psb_backlight_device);
13689c78134cc54dff016c83367912eb055637fa50cAlan Cox
13789c78134cc54dff016c83367912eb055637fa50cAlan Cox	ret = psb_backlight_setup(dev);
13889c78134cc54dff016c83367912eb055637fa50cAlan Cox	if (ret < 0) {
13989c78134cc54dff016c83367912eb055637fa50cAlan Cox		backlight_device_unregister(psb_backlight_device);
14089c78134cc54dff016c83367912eb055637fa50cAlan Cox		psb_backlight_device = NULL;
14189c78134cc54dff016c83367912eb055637fa50cAlan Cox		return ret;
14289c78134cc54dff016c83367912eb055637fa50cAlan Cox	}
14389c78134cc54dff016c83367912eb055637fa50cAlan Cox	psb_backlight_device->props.brightness = 100;
14489c78134cc54dff016c83367912eb055637fa50cAlan Cox	psb_backlight_device->props.max_brightness = 100;
14589c78134cc54dff016c83367912eb055637fa50cAlan Cox	backlight_update_status(psb_backlight_device);
14689c78134cc54dff016c83367912eb055637fa50cAlan Cox	dev_priv->backlight_device = psb_backlight_device;
14789c78134cc54dff016c83367912eb055637fa50cAlan Cox	return 0;
14889c78134cc54dff016c83367912eb055637fa50cAlan Cox}
14989c78134cc54dff016c83367912eb055637fa50cAlan Cox
15089c78134cc54dff016c83367912eb055637fa50cAlan Cox#endif
15189c78134cc54dff016c83367912eb055637fa50cAlan Cox
15289c78134cc54dff016c83367912eb055637fa50cAlan Cox/*
15389c78134cc54dff016c83367912eb055637fa50cAlan Cox *	Provide the Poulsbo specific chip logic and low level methods
15489c78134cc54dff016c83367912eb055637fa50cAlan Cox *	for power management
15589c78134cc54dff016c83367912eb055637fa50cAlan Cox */
15689c78134cc54dff016c83367912eb055637fa50cAlan Cox
15789c78134cc54dff016c83367912eb055637fa50cAlan Coxstatic void psb_init_pm(struct drm_device *dev)
15889c78134cc54dff016c83367912eb055637fa50cAlan Cox{
15989c78134cc54dff016c83367912eb055637fa50cAlan Cox	struct drm_psb_private *dev_priv = dev->dev_private;
16089c78134cc54dff016c83367912eb055637fa50cAlan Cox
16189c78134cc54dff016c83367912eb055637fa50cAlan Cox	u32 gating = PSB_RSGX32(PSB_CR_CLKGATECTL);
16289c78134cc54dff016c83367912eb055637fa50cAlan Cox	gating &= ~3;	/* Disable 2D clock gating */
16389c78134cc54dff016c83367912eb055637fa50cAlan Cox	gating |= 1;
16489c78134cc54dff016c83367912eb055637fa50cAlan Cox	PSB_WSGX32(gating, PSB_CR_CLKGATECTL);
16589c78134cc54dff016c83367912eb055637fa50cAlan Cox	PSB_RSGX32(PSB_CR_CLKGATECTL);
16689c78134cc54dff016c83367912eb055637fa50cAlan Cox}
16789c78134cc54dff016c83367912eb055637fa50cAlan Cox
16889c78134cc54dff016c83367912eb055637fa50cAlan Cox/**
16989c78134cc54dff016c83367912eb055637fa50cAlan Cox *	psb_save_display_registers	-	save registers lost on suspend
17089c78134cc54dff016c83367912eb055637fa50cAlan Cox *	@dev: our DRM device
17189c78134cc54dff016c83367912eb055637fa50cAlan Cox *
17289c78134cc54dff016c83367912eb055637fa50cAlan Cox *	Save the state we need in order to be able to restore the interface
17389c78134cc54dff016c83367912eb055637fa50cAlan Cox *	upon resume from suspend
17489c78134cc54dff016c83367912eb055637fa50cAlan Cox */
17589c78134cc54dff016c83367912eb055637fa50cAlan Coxstatic int psb_save_display_registers(struct drm_device *dev)
17689c78134cc54dff016c83367912eb055637fa50cAlan Cox{
17789c78134cc54dff016c83367912eb055637fa50cAlan Cox	struct drm_psb_private *dev_priv = dev->dev_private;
17889c78134cc54dff016c83367912eb055637fa50cAlan Cox	struct drm_crtc *crtc;
17989c78134cc54dff016c83367912eb055637fa50cAlan Cox	struct drm_connector *connector;
180c6265ff593467d472814aa9f16f89f6c1dc90a5dAlan Cox	struct psb_state *regs = &dev_priv->regs.psb;
18189c78134cc54dff016c83367912eb055637fa50cAlan Cox
18289c78134cc54dff016c83367912eb055637fa50cAlan Cox	/* Display arbitration control + watermarks */
183648a8e342c5a754bdc62f003d3af90507c1abfdeAlan Cox	regs->saveDSPARB = PSB_RVDC32(DSPARB);
184648a8e342c5a754bdc62f003d3af90507c1abfdeAlan Cox	regs->saveDSPFW1 = PSB_RVDC32(DSPFW1);
185648a8e342c5a754bdc62f003d3af90507c1abfdeAlan Cox	regs->saveDSPFW2 = PSB_RVDC32(DSPFW2);
186648a8e342c5a754bdc62f003d3af90507c1abfdeAlan Cox	regs->saveDSPFW3 = PSB_RVDC32(DSPFW3);
187648a8e342c5a754bdc62f003d3af90507c1abfdeAlan Cox	regs->saveDSPFW4 = PSB_RVDC32(DSPFW4);
188648a8e342c5a754bdc62f003d3af90507c1abfdeAlan Cox	regs->saveDSPFW5 = PSB_RVDC32(DSPFW5);
189648a8e342c5a754bdc62f003d3af90507c1abfdeAlan Cox	regs->saveDSPFW6 = PSB_RVDC32(DSPFW6);
190648a8e342c5a754bdc62f003d3af90507c1abfdeAlan Cox	regs->saveCHICKENBIT = PSB_RVDC32(DSPCHICKENBIT);
19189c78134cc54dff016c83367912eb055637fa50cAlan Cox
19289c78134cc54dff016c83367912eb055637fa50cAlan Cox	/* Save crtc and output state */
19389c78134cc54dff016c83367912eb055637fa50cAlan Cox	mutex_lock(&dev->mode_config.mutex);
19489c78134cc54dff016c83367912eb055637fa50cAlan Cox	list_for_each_entry(crtc, &dev->mode_config.crtc_list, head) {
19589c78134cc54dff016c83367912eb055637fa50cAlan Cox		if (drm_helper_crtc_in_use(crtc))
19689c78134cc54dff016c83367912eb055637fa50cAlan Cox			crtc->funcs->save(crtc);
19789c78134cc54dff016c83367912eb055637fa50cAlan Cox	}
19889c78134cc54dff016c83367912eb055637fa50cAlan Cox
19989c78134cc54dff016c83367912eb055637fa50cAlan Cox	list_for_each_entry(connector, &dev->mode_config.connector_list, head)
20089c78134cc54dff016c83367912eb055637fa50cAlan Cox		connector->funcs->save(connector);
20189c78134cc54dff016c83367912eb055637fa50cAlan Cox
20289c78134cc54dff016c83367912eb055637fa50cAlan Cox	mutex_unlock(&dev->mode_config.mutex);
20389c78134cc54dff016c83367912eb055637fa50cAlan Cox	return 0;
20489c78134cc54dff016c83367912eb055637fa50cAlan Cox}
20589c78134cc54dff016c83367912eb055637fa50cAlan Cox
20689c78134cc54dff016c83367912eb055637fa50cAlan Cox/**
20789c78134cc54dff016c83367912eb055637fa50cAlan Cox *	psb_restore_display_registers	-	restore lost register state
20889c78134cc54dff016c83367912eb055637fa50cAlan Cox *	@dev: our DRM device
20989c78134cc54dff016c83367912eb055637fa50cAlan Cox *
21089c78134cc54dff016c83367912eb055637fa50cAlan Cox *	Restore register state that was lost during suspend and resume.
21189c78134cc54dff016c83367912eb055637fa50cAlan Cox */
21289c78134cc54dff016c83367912eb055637fa50cAlan Coxstatic int psb_restore_display_registers(struct drm_device *dev)
21389c78134cc54dff016c83367912eb055637fa50cAlan Cox{
21489c78134cc54dff016c83367912eb055637fa50cAlan Cox	struct drm_psb_private *dev_priv = dev->dev_private;
21589c78134cc54dff016c83367912eb055637fa50cAlan Cox	struct drm_crtc *crtc;
21689c78134cc54dff016c83367912eb055637fa50cAlan Cox	struct drm_connector *connector;
217c6265ff593467d472814aa9f16f89f6c1dc90a5dAlan Cox	struct psb_state *regs = &dev_priv->regs.psb;
21889c78134cc54dff016c83367912eb055637fa50cAlan Cox
21989c78134cc54dff016c83367912eb055637fa50cAlan Cox	/* Display arbitration + watermarks */
220648a8e342c5a754bdc62f003d3af90507c1abfdeAlan Cox	PSB_WVDC32(regs->saveDSPARB, DSPARB);
221648a8e342c5a754bdc62f003d3af90507c1abfdeAlan Cox	PSB_WVDC32(regs->saveDSPFW1, DSPFW1);
222648a8e342c5a754bdc62f003d3af90507c1abfdeAlan Cox	PSB_WVDC32(regs->saveDSPFW2, DSPFW2);
223648a8e342c5a754bdc62f003d3af90507c1abfdeAlan Cox	PSB_WVDC32(regs->saveDSPFW3, DSPFW3);
224648a8e342c5a754bdc62f003d3af90507c1abfdeAlan Cox	PSB_WVDC32(regs->saveDSPFW4, DSPFW4);
225648a8e342c5a754bdc62f003d3af90507c1abfdeAlan Cox	PSB_WVDC32(regs->saveDSPFW5, DSPFW5);
226648a8e342c5a754bdc62f003d3af90507c1abfdeAlan Cox	PSB_WVDC32(regs->saveDSPFW6, DSPFW6);
227648a8e342c5a754bdc62f003d3af90507c1abfdeAlan Cox	PSB_WVDC32(regs->saveCHICKENBIT, DSPCHICKENBIT);
22889c78134cc54dff016c83367912eb055637fa50cAlan Cox
22989c78134cc54dff016c83367912eb055637fa50cAlan Cox	/*make sure VGA plane is off. it initializes to on after reset!*/
23089c78134cc54dff016c83367912eb055637fa50cAlan Cox	PSB_WVDC32(0x80000000, VGACNTRL);
23189c78134cc54dff016c83367912eb055637fa50cAlan Cox
23289c78134cc54dff016c83367912eb055637fa50cAlan Cox	mutex_lock(&dev->mode_config.mutex);
23389c78134cc54dff016c83367912eb055637fa50cAlan Cox	list_for_each_entry(crtc, &dev->mode_config.crtc_list, head)
23489c78134cc54dff016c83367912eb055637fa50cAlan Cox		if (drm_helper_crtc_in_use(crtc))
23589c78134cc54dff016c83367912eb055637fa50cAlan Cox			crtc->funcs->restore(crtc);
23689c78134cc54dff016c83367912eb055637fa50cAlan Cox
23789c78134cc54dff016c83367912eb055637fa50cAlan Cox	list_for_each_entry(connector, &dev->mode_config.connector_list, head)
23889c78134cc54dff016c83367912eb055637fa50cAlan Cox		connector->funcs->restore(connector);
23989c78134cc54dff016c83367912eb055637fa50cAlan Cox
24089c78134cc54dff016c83367912eb055637fa50cAlan Cox	mutex_unlock(&dev->mode_config.mutex);
24189c78134cc54dff016c83367912eb055637fa50cAlan Cox	return 0;
24289c78134cc54dff016c83367912eb055637fa50cAlan Cox}
24389c78134cc54dff016c83367912eb055637fa50cAlan Cox
24489c78134cc54dff016c83367912eb055637fa50cAlan Coxstatic int psb_power_down(struct drm_device *dev)
24589c78134cc54dff016c83367912eb055637fa50cAlan Cox{
24689c78134cc54dff016c83367912eb055637fa50cAlan Cox	return 0;
24789c78134cc54dff016c83367912eb055637fa50cAlan Cox}
24889c78134cc54dff016c83367912eb055637fa50cAlan Cox
24989c78134cc54dff016c83367912eb055637fa50cAlan Coxstatic int psb_power_up(struct drm_device *dev)
25089c78134cc54dff016c83367912eb055637fa50cAlan Cox{
25189c78134cc54dff016c83367912eb055637fa50cAlan Cox	return 0;
25289c78134cc54dff016c83367912eb055637fa50cAlan Cox}
25389c78134cc54dff016c83367912eb055637fa50cAlan Cox
25489c78134cc54dff016c83367912eb055637fa50cAlan Coxstatic void psb_get_core_freq(struct drm_device *dev)
25589c78134cc54dff016c83367912eb055637fa50cAlan Cox{
25689c78134cc54dff016c83367912eb055637fa50cAlan Cox	uint32_t clock;
25789c78134cc54dff016c83367912eb055637fa50cAlan Cox	struct pci_dev *pci_root = pci_get_bus_and_slot(0, 0);
25889c78134cc54dff016c83367912eb055637fa50cAlan Cox	struct drm_psb_private *dev_priv = dev->dev_private;
25989c78134cc54dff016c83367912eb055637fa50cAlan Cox
26089c78134cc54dff016c83367912eb055637fa50cAlan Cox	/*pci_write_config_dword(pci_root, 0xD4, 0x00C32004);*/
26189c78134cc54dff016c83367912eb055637fa50cAlan Cox	/*pci_write_config_dword(pci_root, 0xD0, 0xE0033000);*/
26289c78134cc54dff016c83367912eb055637fa50cAlan Cox
26389c78134cc54dff016c83367912eb055637fa50cAlan Cox	pci_write_config_dword(pci_root, 0xD0, 0xD0050300);
26489c78134cc54dff016c83367912eb055637fa50cAlan Cox	pci_read_config_dword(pci_root, 0xD4, &clock);
26589c78134cc54dff016c83367912eb055637fa50cAlan Cox	pci_dev_put(pci_root);
26689c78134cc54dff016c83367912eb055637fa50cAlan Cox
26789c78134cc54dff016c83367912eb055637fa50cAlan Cox	switch (clock & 0x07) {
26889c78134cc54dff016c83367912eb055637fa50cAlan Cox	case 0:
26989c78134cc54dff016c83367912eb055637fa50cAlan Cox		dev_priv->core_freq = 100;
27089c78134cc54dff016c83367912eb055637fa50cAlan Cox		break;
27189c78134cc54dff016c83367912eb055637fa50cAlan Cox	case 1:
27289c78134cc54dff016c83367912eb055637fa50cAlan Cox		dev_priv->core_freq = 133;
27389c78134cc54dff016c83367912eb055637fa50cAlan Cox		break;
27489c78134cc54dff016c83367912eb055637fa50cAlan Cox	case 2:
27589c78134cc54dff016c83367912eb055637fa50cAlan Cox		dev_priv->core_freq = 150;
27689c78134cc54dff016c83367912eb055637fa50cAlan Cox		break;
27789c78134cc54dff016c83367912eb055637fa50cAlan Cox	case 3:
27889c78134cc54dff016c83367912eb055637fa50cAlan Cox		dev_priv->core_freq = 178;
27989c78134cc54dff016c83367912eb055637fa50cAlan Cox		break;
28089c78134cc54dff016c83367912eb055637fa50cAlan Cox	case 4:
28189c78134cc54dff016c83367912eb055637fa50cAlan Cox		dev_priv->core_freq = 200;
28289c78134cc54dff016c83367912eb055637fa50cAlan Cox		break;
28389c78134cc54dff016c83367912eb055637fa50cAlan Cox	case 5:
28489c78134cc54dff016c83367912eb055637fa50cAlan Cox	case 6:
28589c78134cc54dff016c83367912eb055637fa50cAlan Cox	case 7:
28689c78134cc54dff016c83367912eb055637fa50cAlan Cox		dev_priv->core_freq = 266;
28789c78134cc54dff016c83367912eb055637fa50cAlan Cox	default:
28889c78134cc54dff016c83367912eb055637fa50cAlan Cox		dev_priv->core_freq = 0;
28989c78134cc54dff016c83367912eb055637fa50cAlan Cox	}
29089c78134cc54dff016c83367912eb055637fa50cAlan Cox}
29189c78134cc54dff016c83367912eb055637fa50cAlan Cox
2928512e0748729a49d9af6693f920c1b432796fa8dAlan Cox/* Poulsbo */
2938512e0748729a49d9af6693f920c1b432796fa8dAlan Coxstatic const struct psb_offset psb_regmap[2] = {
2948512e0748729a49d9af6693f920c1b432796fa8dAlan Cox	{
2958512e0748729a49d9af6693f920c1b432796fa8dAlan Cox		.fp0 = FPA0,
2968512e0748729a49d9af6693f920c1b432796fa8dAlan Cox		.fp1 = FPA1,
2978512e0748729a49d9af6693f920c1b432796fa8dAlan Cox		.cntr = DSPACNTR,
2988512e0748729a49d9af6693f920c1b432796fa8dAlan Cox		.conf = PIPEACONF,
2998512e0748729a49d9af6693f920c1b432796fa8dAlan Cox		.src = PIPEASRC,
3008512e0748729a49d9af6693f920c1b432796fa8dAlan Cox		.dpll = DPLL_A,
3018512e0748729a49d9af6693f920c1b432796fa8dAlan Cox		.htotal = HTOTAL_A,
3028512e0748729a49d9af6693f920c1b432796fa8dAlan Cox		.hblank = HBLANK_A,
3038512e0748729a49d9af6693f920c1b432796fa8dAlan Cox		.hsync = HSYNC_A,
3048512e0748729a49d9af6693f920c1b432796fa8dAlan Cox		.vtotal = VTOTAL_A,
3058512e0748729a49d9af6693f920c1b432796fa8dAlan Cox		.vblank = VBLANK_A,
3068512e0748729a49d9af6693f920c1b432796fa8dAlan Cox		.vsync = VSYNC_A,
3078512e0748729a49d9af6693f920c1b432796fa8dAlan Cox		.stride = DSPASTRIDE,
3088512e0748729a49d9af6693f920c1b432796fa8dAlan Cox		.size = DSPASIZE,
3098512e0748729a49d9af6693f920c1b432796fa8dAlan Cox		.pos = DSPAPOS,
3108512e0748729a49d9af6693f920c1b432796fa8dAlan Cox		.base = DSPABASE,
3118512e0748729a49d9af6693f920c1b432796fa8dAlan Cox		.surf = DSPASURF,
3128512e0748729a49d9af6693f920c1b432796fa8dAlan Cox		.addr = DSPABASE,
3138512e0748729a49d9af6693f920c1b432796fa8dAlan Cox		.status = PIPEASTAT,
3148512e0748729a49d9af6693f920c1b432796fa8dAlan Cox		.linoff = DSPALINOFF,
3158512e0748729a49d9af6693f920c1b432796fa8dAlan Cox		.tileoff = DSPATILEOFF,
3168512e0748729a49d9af6693f920c1b432796fa8dAlan Cox		.palette = PALETTE_A,
3178512e0748729a49d9af6693f920c1b432796fa8dAlan Cox	},
3188512e0748729a49d9af6693f920c1b432796fa8dAlan Cox	{
3198512e0748729a49d9af6693f920c1b432796fa8dAlan Cox		.fp0 = FPB0,
3208512e0748729a49d9af6693f920c1b432796fa8dAlan Cox		.fp1 = FPB1,
3218512e0748729a49d9af6693f920c1b432796fa8dAlan Cox		.cntr = DSPBCNTR,
3228512e0748729a49d9af6693f920c1b432796fa8dAlan Cox		.conf = PIPEBCONF,
3238512e0748729a49d9af6693f920c1b432796fa8dAlan Cox		.src = PIPEBSRC,
3248512e0748729a49d9af6693f920c1b432796fa8dAlan Cox		.dpll = DPLL_B,
3258512e0748729a49d9af6693f920c1b432796fa8dAlan Cox		.htotal = HTOTAL_B,
3268512e0748729a49d9af6693f920c1b432796fa8dAlan Cox		.hblank = HBLANK_B,
3278512e0748729a49d9af6693f920c1b432796fa8dAlan Cox		.hsync = HSYNC_B,
3288512e0748729a49d9af6693f920c1b432796fa8dAlan Cox		.vtotal = VTOTAL_B,
3298512e0748729a49d9af6693f920c1b432796fa8dAlan Cox		.vblank = VBLANK_B,
3308512e0748729a49d9af6693f920c1b432796fa8dAlan Cox		.vsync = VSYNC_B,
3318512e0748729a49d9af6693f920c1b432796fa8dAlan Cox		.stride = DSPBSTRIDE,
3328512e0748729a49d9af6693f920c1b432796fa8dAlan Cox		.size = DSPBSIZE,
3338512e0748729a49d9af6693f920c1b432796fa8dAlan Cox		.pos = DSPBPOS,
3348512e0748729a49d9af6693f920c1b432796fa8dAlan Cox		.base = DSPBBASE,
3358512e0748729a49d9af6693f920c1b432796fa8dAlan Cox		.surf = DSPBSURF,
3368512e0748729a49d9af6693f920c1b432796fa8dAlan Cox		.addr = DSPBBASE,
3378512e0748729a49d9af6693f920c1b432796fa8dAlan Cox		.status = PIPEBSTAT,
3388512e0748729a49d9af6693f920c1b432796fa8dAlan Cox		.linoff = DSPBLINOFF,
3398512e0748729a49d9af6693f920c1b432796fa8dAlan Cox		.tileoff = DSPBTILEOFF,
3408512e0748729a49d9af6693f920c1b432796fa8dAlan Cox		.palette = PALETTE_B,
3418512e0748729a49d9af6693f920c1b432796fa8dAlan Cox	}
3428512e0748729a49d9af6693f920c1b432796fa8dAlan Cox};
3438512e0748729a49d9af6693f920c1b432796fa8dAlan Cox
34489c78134cc54dff016c83367912eb055637fa50cAlan Coxstatic int psb_chip_setup(struct drm_device *dev)
34589c78134cc54dff016c83367912eb055637fa50cAlan Cox{
3468512e0748729a49d9af6693f920c1b432796fa8dAlan Cox	struct drm_psb_private *dev_priv = dev->dev_private;
3478512e0748729a49d9af6693f920c1b432796fa8dAlan Cox	dev_priv->regmap = psb_regmap;
34889c78134cc54dff016c83367912eb055637fa50cAlan Cox	psb_get_core_freq(dev);
3495c0c1d50d7ba7a678b7d6e2c4f2ff31edafb1067Patrik Jakobsson	gma_intel_setup_gmbus(dev);
350d839ede47a56ff5f316c88391818488f8e5913afAlan Cox	psb_intel_opregion_init(dev);
35189c78134cc54dff016c83367912eb055637fa50cAlan Cox	psb_intel_init_bios(dev);
35289c78134cc54dff016c83367912eb055637fa50cAlan Cox	return 0;
35389c78134cc54dff016c83367912eb055637fa50cAlan Cox}
35489c78134cc54dff016c83367912eb055637fa50cAlan Cox
3556607e024014e4920e8d3e43bcfeec0436d43d980Alan Cox/* Not exactly an erratum more an irritation */
3560333592ff9e936c6e5ae143e7418468a3198b54dDave Airliestatic void psb_chip_errata(struct drm_device *dev)
3576607e024014e4920e8d3e43bcfeec0436d43d980Alan Cox{
3586607e024014e4920e8d3e43bcfeec0436d43d980Alan Cox	struct drm_psb_private *dev_priv = dev->dev_private;
3596607e024014e4920e8d3e43bcfeec0436d43d980Alan Cox	psb_lid_timer_init(dev_priv);
3606607e024014e4920e8d3e43bcfeec0436d43d980Alan Cox}
3616607e024014e4920e8d3e43bcfeec0436d43d980Alan Cox
3625c0c1d50d7ba7a678b7d6e2c4f2ff31edafb1067Patrik Jakobssonstatic void psb_chip_teardown(struct drm_device *dev)
3635c0c1d50d7ba7a678b7d6e2c4f2ff31edafb1067Patrik Jakobsson{
3646607e024014e4920e8d3e43bcfeec0436d43d980Alan Cox	struct drm_psb_private *dev_priv = dev->dev_private;
3656607e024014e4920e8d3e43bcfeec0436d43d980Alan Cox	psb_lid_timer_takedown(dev_priv);
3665c0c1d50d7ba7a678b7d6e2c4f2ff31edafb1067Patrik Jakobsson	gma_intel_teardown_gmbus(dev);
3675c0c1d50d7ba7a678b7d6e2c4f2ff31edafb1067Patrik Jakobsson}
3685c0c1d50d7ba7a678b7d6e2c4f2ff31edafb1067Patrik Jakobsson
36989c78134cc54dff016c83367912eb055637fa50cAlan Coxconst struct psb_ops psb_chip_ops = {
37089c78134cc54dff016c83367912eb055637fa50cAlan Cox	.name = "Poulsbo",
37189c78134cc54dff016c83367912eb055637fa50cAlan Cox	.accel_2d = 1,
37289c78134cc54dff016c83367912eb055637fa50cAlan Cox	.pipes = 2,
37389c78134cc54dff016c83367912eb055637fa50cAlan Cox	.crtcs = 2,
374d235e64a4367ad3ff204309490c4325b4f89b25bAlan Cox	.hdmi_mask = (1 << 0),
375d235e64a4367ad3ff204309490c4325b4f89b25bAlan Cox	.lvds_mask = (1 << 1),
376bc794829141f28e14fe7d0e07e35870bd9aee78cPatrik Jakobsson	.cursor_needs_phys = 1,
37789c78134cc54dff016c83367912eb055637fa50cAlan Cox	.sgx_offset = PSB_SGX_OFFSET,
37889c78134cc54dff016c83367912eb055637fa50cAlan Cox	.chip_setup = psb_chip_setup,
3795c0c1d50d7ba7a678b7d6e2c4f2ff31edafb1067Patrik Jakobsson	.chip_teardown = psb_chip_teardown,
3806607e024014e4920e8d3e43bcfeec0436d43d980Alan Cox	.errata = psb_chip_errata,
38189c78134cc54dff016c83367912eb055637fa50cAlan Cox
38289c78134cc54dff016c83367912eb055637fa50cAlan Cox	.crtc_helper = &psb_intel_helper_funcs,
38389c78134cc54dff016c83367912eb055637fa50cAlan Cox	.crtc_funcs = &psb_intel_crtc_funcs,
38489c78134cc54dff016c83367912eb055637fa50cAlan Cox
38589c78134cc54dff016c83367912eb055637fa50cAlan Cox	.output_init = psb_output_init,
38689c78134cc54dff016c83367912eb055637fa50cAlan Cox
38789c78134cc54dff016c83367912eb055637fa50cAlan Cox#ifdef CONFIG_BACKLIGHT_CLASS_DEVICE
38889c78134cc54dff016c83367912eb055637fa50cAlan Cox	.backlight_init = psb_backlight_init,
38989c78134cc54dff016c83367912eb055637fa50cAlan Cox#endif
39089c78134cc54dff016c83367912eb055637fa50cAlan Cox
39189c78134cc54dff016c83367912eb055637fa50cAlan Cox	.init_pm = psb_init_pm,
39289c78134cc54dff016c83367912eb055637fa50cAlan Cox	.save_regs = psb_save_display_registers,
39389c78134cc54dff016c83367912eb055637fa50cAlan Cox	.restore_regs = psb_restore_display_registers,
39489c78134cc54dff016c83367912eb055637fa50cAlan Cox	.power_down = psb_power_down,
39589c78134cc54dff016c83367912eb055637fa50cAlan Cox	.power_up = psb_power_up,
39689c78134cc54dff016c83367912eb055637fa50cAlan Cox};
39789c78134cc54dff016c83367912eb055637fa50cAlan Cox
398