1 | // SPDX-License-Identifier: GPL-2.0-only |
2 | /************************************************************************** |
3 | * Copyright (c) 2007, Intel Corporation. |
4 | * |
5 | * Authors: Thomas Hellstrom <thomas-at-tungstengraphics-dot-com> |
6 | **************************************************************************/ |
7 | |
8 | #include <linux/spinlock.h> |
9 | |
10 | #include "psb_drv.h" |
11 | #include "psb_intel_reg.h" |
12 | #include "psb_reg.h" |
13 | |
14 | static void psb_lid_timer_func(struct timer_list *t) |
15 | { |
16 | struct drm_psb_private *dev_priv = from_timer(dev_priv, t, lid_timer); |
17 | struct drm_device *dev = (struct drm_device *)&dev_priv->dev; |
18 | struct timer_list *lid_timer = &dev_priv->lid_timer; |
19 | unsigned long irq_flags; |
20 | u32 __iomem *lid_state = dev_priv->opregion.lid_state; |
21 | u32 pp_status; |
22 | |
23 | if (readl(addr: lid_state) == dev_priv->lid_last_state) |
24 | goto lid_timer_schedule; |
25 | |
26 | if ((readl(addr: lid_state)) & 0x01) { |
27 | /*lid state is open*/ |
28 | REG_WRITE(PP_CONTROL, REG_READ(PP_CONTROL) | POWER_TARGET_ON); |
29 | do { |
30 | pp_status = REG_READ(PP_STATUS); |
31 | } while ((pp_status & PP_ON) == 0 && |
32 | (pp_status & PP_SEQUENCE_MASK) != 0); |
33 | |
34 | if (REG_READ(PP_STATUS) & PP_ON) { |
35 | /*FIXME: should be backlight level before*/ |
36 | psb_intel_lvds_set_brightness(dev, level: 100); |
37 | } else { |
38 | DRM_DEBUG("LVDS panel never powered up" ); |
39 | return; |
40 | } |
41 | } else { |
42 | psb_intel_lvds_set_brightness(dev, level: 0); |
43 | |
44 | REG_WRITE(PP_CONTROL, REG_READ(PP_CONTROL) & ~POWER_TARGET_ON); |
45 | do { |
46 | pp_status = REG_READ(PP_STATUS); |
47 | } while ((pp_status & PP_ON) == 0); |
48 | } |
49 | dev_priv->lid_last_state = readl(addr: lid_state); |
50 | |
51 | lid_timer_schedule: |
52 | spin_lock_irqsave(&dev_priv->lid_lock, irq_flags); |
53 | if (!timer_pending(timer: lid_timer)) { |
54 | lid_timer->expires = jiffies + PSB_LID_DELAY; |
55 | add_timer(timer: lid_timer); |
56 | } |
57 | spin_unlock_irqrestore(lock: &dev_priv->lid_lock, flags: irq_flags); |
58 | } |
59 | |
60 | void psb_lid_timer_init(struct drm_psb_private *dev_priv) |
61 | { |
62 | struct timer_list *lid_timer = &dev_priv->lid_timer; |
63 | unsigned long irq_flags; |
64 | |
65 | spin_lock_init(&dev_priv->lid_lock); |
66 | spin_lock_irqsave(&dev_priv->lid_lock, irq_flags); |
67 | |
68 | timer_setup(lid_timer, psb_lid_timer_func, 0); |
69 | |
70 | lid_timer->expires = jiffies + PSB_LID_DELAY; |
71 | |
72 | add_timer(timer: lid_timer); |
73 | spin_unlock_irqrestore(lock: &dev_priv->lid_lock, flags: irq_flags); |
74 | } |
75 | |
76 | void psb_lid_timer_takedown(struct drm_psb_private *dev_priv) |
77 | { |
78 | del_timer_sync(timer: &dev_priv->lid_timer); |
79 | } |
80 | |
81 | |