linux/drivers/gpu/drm/gma500/psb_lid.c
<<
>>
Prefs
   1/**************************************************************************
   2 * Copyright (c) 2007, Intel Corporation.
   3 *
   4 * This program is free software; you can redistribute it and/or modify it
   5 * under the terms and conditions of the GNU General Public License,
   6 * version 2, as published by the Free Software Foundation.
   7 *
   8 * This program is distributed in the hope it will be useful, but WITHOUT
   9 * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
  10 * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License for
  11 * more details.
  12 *
  13 * You should have received a copy of the GNU General Public License along with
  14 * this program; if not, write to the Free Software Foundation, Inc.,
  15 * 51 Franklin St - Fifth Floor, Boston, MA 02110-1301 USA.
  16 *
  17 * Authors: Thomas Hellstrom <thomas-at-tungstengraphics-dot-com>
  18 **************************************************************************/
  19
  20#include <drm/drmP.h>
  21#include "psb_drv.h"
  22#include "psb_reg.h"
  23#include "psb_intel_reg.h"
  24#include <linux/spinlock.h>
  25
  26static void psb_lid_timer_func(unsigned long data)
  27{
  28        struct drm_psb_private * dev_priv = (struct drm_psb_private *)data;
  29        struct drm_device *dev = (struct drm_device *)dev_priv->dev;
  30        struct timer_list *lid_timer = &dev_priv->lid_timer;
  31        unsigned long irq_flags;
  32        u32 __iomem *lid_state = dev_priv->opregion.lid_state;
  33        u32 pp_status;
  34
  35        if (readl(lid_state) == dev_priv->lid_last_state)
  36                goto lid_timer_schedule;
  37
  38        if ((readl(lid_state)) & 0x01) {
  39                /*lid state is open*/
  40                REG_WRITE(PP_CONTROL, REG_READ(PP_CONTROL) | POWER_TARGET_ON);
  41                do {
  42                        pp_status = REG_READ(PP_STATUS);
  43                } while ((pp_status & PP_ON) == 0 &&
  44                         (pp_status & PP_SEQUENCE_MASK) != 0);
  45
  46                if (REG_READ(PP_STATUS) & PP_ON) {
  47                        /*FIXME: should be backlight level before*/
  48                        psb_intel_lvds_set_brightness(dev, 100);
  49                } else {
  50                        DRM_DEBUG("LVDS panel never powered up");
  51                        return;
  52                }
  53        } else {
  54                psb_intel_lvds_set_brightness(dev, 0);
  55
  56                REG_WRITE(PP_CONTROL, REG_READ(PP_CONTROL) & ~POWER_TARGET_ON);
  57                do {
  58                        pp_status = REG_READ(PP_STATUS);
  59                } while ((pp_status & PP_ON) == 0);
  60        }
  61        dev_priv->lid_last_state =  readl(lid_state);
  62
  63lid_timer_schedule:
  64        spin_lock_irqsave(&dev_priv->lid_lock, irq_flags);
  65        if (!timer_pending(lid_timer)) {
  66                lid_timer->expires = jiffies + PSB_LID_DELAY;
  67                add_timer(lid_timer);
  68        }
  69        spin_unlock_irqrestore(&dev_priv->lid_lock, irq_flags);
  70}
  71
  72void psb_lid_timer_init(struct drm_psb_private *dev_priv)
  73{
  74        struct timer_list *lid_timer = &dev_priv->lid_timer;
  75        unsigned long irq_flags;
  76
  77        spin_lock_init(&dev_priv->lid_lock);
  78        spin_lock_irqsave(&dev_priv->lid_lock, irq_flags);
  79
  80        init_timer(lid_timer);
  81
  82        lid_timer->data = (unsigned long)dev_priv;
  83        lid_timer->function = psb_lid_timer_func;
  84        lid_timer->expires = jiffies + PSB_LID_DELAY;
  85
  86        add_timer(lid_timer);
  87        spin_unlock_irqrestore(&dev_priv->lid_lock, irq_flags);
  88}
  89
  90void psb_lid_timer_takedown(struct drm_psb_private *dev_priv)
  91{
  92        del_timer_sync(&dev_priv->lid_timer);
  93}
  94
  95