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