0001
0002
0003
0004
0005
0006
0007
0008 #include <linux/spinlock.h>
0009
0010 #include "psb_drv.h"
0011 #include "psb_intel_reg.h"
0012 #include "psb_reg.h"
0013
0014 static void psb_lid_timer_func(struct timer_list *t)
0015 {
0016 struct drm_psb_private *dev_priv = from_timer(dev_priv, t, lid_timer);
0017 struct drm_device *dev = (struct drm_device *)&dev_priv->dev;
0018 struct timer_list *lid_timer = &dev_priv->lid_timer;
0019 unsigned long irq_flags;
0020 u32 __iomem *lid_state = dev_priv->opregion.lid_state;
0021 u32 pp_status;
0022
0023 if (readl(lid_state) == dev_priv->lid_last_state)
0024 goto lid_timer_schedule;
0025
0026 if ((readl(lid_state)) & 0x01) {
0027
0028 REG_WRITE(PP_CONTROL, REG_READ(PP_CONTROL) | POWER_TARGET_ON);
0029 do {
0030 pp_status = REG_READ(PP_STATUS);
0031 } while ((pp_status & PP_ON) == 0 &&
0032 (pp_status & PP_SEQUENCE_MASK) != 0);
0033
0034 if (REG_READ(PP_STATUS) & PP_ON) {
0035
0036 psb_intel_lvds_set_brightness(dev, 100);
0037 } else {
0038 DRM_DEBUG("LVDS panel never powered up");
0039 return;
0040 }
0041 } else {
0042 psb_intel_lvds_set_brightness(dev, 0);
0043
0044 REG_WRITE(PP_CONTROL, REG_READ(PP_CONTROL) & ~POWER_TARGET_ON);
0045 do {
0046 pp_status = REG_READ(PP_STATUS);
0047 } while ((pp_status & PP_ON) == 0);
0048 }
0049 dev_priv->lid_last_state = readl(lid_state);
0050
0051 lid_timer_schedule:
0052 spin_lock_irqsave(&dev_priv->lid_lock, irq_flags);
0053 if (!timer_pending(lid_timer)) {
0054 lid_timer->expires = jiffies + PSB_LID_DELAY;
0055 add_timer(lid_timer);
0056 }
0057 spin_unlock_irqrestore(&dev_priv->lid_lock, irq_flags);
0058 }
0059
0060 void psb_lid_timer_init(struct drm_psb_private *dev_priv)
0061 {
0062 struct timer_list *lid_timer = &dev_priv->lid_timer;
0063 unsigned long irq_flags;
0064
0065 spin_lock_init(&dev_priv->lid_lock);
0066 spin_lock_irqsave(&dev_priv->lid_lock, irq_flags);
0067
0068 timer_setup(lid_timer, psb_lid_timer_func, 0);
0069
0070 lid_timer->expires = jiffies + PSB_LID_DELAY;
0071
0072 add_timer(lid_timer);
0073 spin_unlock_irqrestore(&dev_priv->lid_lock, irq_flags);
0074 }
0075
0076 void psb_lid_timer_takedown(struct drm_psb_private *dev_priv)
0077 {
0078 del_timer_sync(&dev_priv->lid_timer);
0079 }
0080