Blame view

drivers/macintosh/via-pmu-backlight.c 4.56 KB
5474c120a   Michael Hanselmann   [PATCH] Rewritten...
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
  /*
   * Backlight code for via-pmu
   *
   * Copyright (C) 1998 Paul Mackerras and Fabio Riccardi.
   * Copyright (C) 2001-2002 Benjamin Herrenschmidt
   * Copyright (C) 2006      Michael Hanselmann <linux-kernel@hansmi.ch>
   *
   */
  
  #include <asm/ptrace.h>
  #include <linux/adb.h>
  #include <linux/pmu.h>
  #include <asm/backlight.h>
  #include <asm/prom.h>
  
  #define MAX_PMU_LEVEL 0xFF
acc2472ed   Lionel Debroux   backlight: consti...
17
  static const struct backlight_ops pmu_backlight_data;
4efd587bf   David Woodhouse   [PATCH] Fix unini...
18
  static DEFINE_SPINLOCK(pmu_backlight_lock);
fa19d6348   Benjamin Herrenschmidt   [POWERPC] Fix sle...
19
  static int sleeping, uses_pmu_bl;
d565dd3b0   Benjamin Herrenschmidt   [PATCH] powerpc: ...
20
  static u8 bl_curve[FB_BACKLIGHT_LEVELS];
5474c120a   Michael Hanselmann   [PATCH] Rewritten...
21

d565dd3b0   Benjamin Herrenschmidt   [PATCH] powerpc: ...
22
23
  static void pmu_backlight_init_curve(u8 off, u8 min, u8 max)
  {
0094f2cdc   Benjamin Herrenschmidt   [POWERPC] Fix for...
24
  	int i, flat, count, range = (max - min);
d565dd3b0   Benjamin Herrenschmidt   [PATCH] powerpc: ...
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
  
  	bl_curve[0] = off;
  
  	for (flat = 1; flat < (FB_BACKLIGHT_LEVELS / 16); ++flat)
  		bl_curve[flat] = min;
  
  	count = FB_BACKLIGHT_LEVELS * 15 / 16;
  	for (i = 0; i < count; ++i)
  		bl_curve[flat + i] = min + (range * (i + 1) / count);
  }
  
  static int pmu_backlight_curve_lookup(int value)
  {
  	int level = (FB_BACKLIGHT_LEVELS - 1);
  	int i, max = 0;
  
  	/* Look for biggest value */
  	for (i = 0; i < FB_BACKLIGHT_LEVELS; i++)
  		max = max((int)bl_curve[i], max);
  
  	/* Look for nearest value */
  	for (i = 0; i < FB_BACKLIGHT_LEVELS; i++) {
  		int diff = abs(bl_curve[i] - value);
  		if (diff < max) {
  			max = diff;
  			level = i;
  		}
  	}
  	return level;
  }
  
  static int pmu_backlight_get_level_brightness(int level)
5474c120a   Michael Hanselmann   [PATCH] Rewritten...
57
58
59
60
  {
  	int pmulevel;
  
  	/* Get and convert the value */
d565dd3b0   Benjamin Herrenschmidt   [PATCH] powerpc: ...
61
  	pmulevel = bl_curve[level] * FB_BACKLIGHT_MAX / MAX_PMU_LEVEL;
5474c120a   Michael Hanselmann   [PATCH] Rewritten...
62
63
64
65
66
67
68
  	if (pmulevel < 0)
  		pmulevel = 0;
  	else if (pmulevel > MAX_PMU_LEVEL)
  		pmulevel = MAX_PMU_LEVEL;
  
  	return pmulevel;
  }
0094f2cdc   Benjamin Herrenschmidt   [POWERPC] Fix for...
69
  static int __pmu_backlight_update_status(struct backlight_device *bd)
5474c120a   Michael Hanselmann   [PATCH] Rewritten...
70
  {
5474c120a   Michael Hanselmann   [PATCH] Rewritten...
71
  	struct adb_request req;
599a52d12   Richard Purdie   backlight: Separa...
72
  	int level = bd->props.brightness;
5474c120a   Michael Hanselmann   [PATCH] Rewritten...
73

5474c120a   Michael Hanselmann   [PATCH] Rewritten...
74

599a52d12   Richard Purdie   backlight: Separa...
75
76
  	if (bd->props.power != FB_BLANK_UNBLANK ||
  	    bd->props.fb_blank != FB_BLANK_UNBLANK)
5474c120a   Michael Hanselmann   [PATCH] Rewritten...
77
  		level = 0;
4b755999d   Michael Hanselmann   [PATCH] powermac:...
78
  	if (level > 0) {
d565dd3b0   Benjamin Herrenschmidt   [PATCH] powerpc: ...
79
  		int pmulevel = pmu_backlight_get_level_brightness(level);
5474c120a   Michael Hanselmann   [PATCH] Rewritten...
80

4b755999d   Michael Hanselmann   [PATCH] powermac:...
81
82
  		pmu_request(&req, NULL, 2, PMU_BACKLIGHT_BRIGHT, pmulevel);
  		pmu_wait_complete(&req);
5474c120a   Michael Hanselmann   [PATCH] Rewritten...
83

4b755999d   Michael Hanselmann   [PATCH] powermac:...
84
85
86
87
88
89
90
91
  		pmu_request(&req, NULL, 2, PMU_POWER_CTRL,
  			PMU_POW_BACKLIGHT | PMU_POW_ON);
  		pmu_wait_complete(&req);
  	} else {
  		pmu_request(&req, NULL, 2, PMU_POWER_CTRL,
  			PMU_POW_BACKLIGHT | PMU_POW_OFF);
  		pmu_wait_complete(&req);
  	}
5474c120a   Michael Hanselmann   [PATCH] Rewritten...
92
93
  	return 0;
  }
0094f2cdc   Benjamin Herrenschmidt   [POWERPC] Fix for...
94
95
96
97
98
99
100
101
102
103
104
105
  static int pmu_backlight_update_status(struct backlight_device *bd)
  {
  	unsigned long flags;
  	int rc = 0;
  
  	spin_lock_irqsave(&pmu_backlight_lock, flags);
  	/* Don't update brightness when sleeping */
  	if (!sleeping)
  		rc = __pmu_backlight_update_status(bd);
  	spin_unlock_irqrestore(&pmu_backlight_lock, flags);
  	return rc;
  }
5474c120a   Michael Hanselmann   [PATCH] Rewritten...
106
107
  static int pmu_backlight_get_brightness(struct backlight_device *bd)
  {
599a52d12   Richard Purdie   backlight: Separa...
108
  	return bd->props.brightness;
5474c120a   Michael Hanselmann   [PATCH] Rewritten...
109
  }
acc2472ed   Lionel Debroux   backlight: consti...
110
  static const struct backlight_ops pmu_backlight_data = {
5474c120a   Michael Hanselmann   [PATCH] Rewritten...
111
112
  	.get_brightness	= pmu_backlight_get_brightness,
  	.update_status	= pmu_backlight_update_status,
599a52d12   Richard Purdie   backlight: Separa...
113

5474c120a   Michael Hanselmann   [PATCH] Rewritten...
114
  };
4b755999d   Michael Hanselmann   [PATCH] powermac:...
115
  #ifdef CONFIG_PM
d565dd3b0   Benjamin Herrenschmidt   [PATCH] powerpc: ...
116
  void pmu_backlight_set_sleep(int sleep)
4b755999d   Michael Hanselmann   [PATCH] powermac:...
117
118
119
120
  {
  	unsigned long flags;
  
  	spin_lock_irqsave(&pmu_backlight_lock, flags);
d565dd3b0   Benjamin Herrenschmidt   [PATCH] powerpc: ...
121
  	sleeping = sleep;
fa19d6348   Benjamin Herrenschmidt   [POWERPC] Fix sle...
122
  	if (pmac_backlight && uses_pmu_bl) {
0094f2cdc   Benjamin Herrenschmidt   [POWERPC] Fix for...
123
124
125
126
127
128
129
130
131
  		if (sleep) {
  			struct adb_request req;
  
  			pmu_request(&req, NULL, 2, PMU_POWER_CTRL,
  				    PMU_POW_BACKLIGHT | PMU_POW_OFF);
  			pmu_wait_complete(&req);
  		} else
  			__pmu_backlight_update_status(pmac_backlight);
  	}
4b755999d   Michael Hanselmann   [PATCH] powermac:...
132
  	spin_unlock_irqrestore(&pmu_backlight_lock, flags);
4b755999d   Michael Hanselmann   [PATCH] powermac:...
133
  }
d565dd3b0   Benjamin Herrenschmidt   [PATCH] powerpc: ...
134
  #endif /* CONFIG_PM */
4b755999d   Michael Hanselmann   [PATCH] powermac:...
135
136
  
  void __init pmu_backlight_init()
5474c120a   Michael Hanselmann   [PATCH] Rewritten...
137
  {
a19a6ee6c   Matthew Garrett   backlight: Allow ...
138
  	struct backlight_properties props;
5474c120a   Michael Hanselmann   [PATCH] Rewritten...
139
  	struct backlight_device *bd;
5474c120a   Michael Hanselmann   [PATCH] Rewritten...
140
141
  	char name[10];
  	int level, autosave;
5474c120a   Michael Hanselmann   [PATCH] Rewritten...
142
143
  	/* Special case for the old PowerBook since I can't test on it */
  	autosave =
71a157e8e   Grant Likely   of: add 'of_' pre...
144
145
  		of_machine_is_compatible("AAPL,3400/2400") ||
  		of_machine_is_compatible("AAPL,3500");
5474c120a   Michael Hanselmann   [PATCH] Rewritten...
146
147
148
  
  	if (!autosave &&
  	    !pmac_has_backlight_type("pmu") &&
71a157e8e   Grant Likely   of: add 'of_' pre...
149
150
  	    !of_machine_is_compatible("AAPL,PowerBook1998") &&
  	    !of_machine_is_compatible("PowerBook1,1"))
5474c120a   Michael Hanselmann   [PATCH] Rewritten...
151
  		return;
d565dd3b0   Benjamin Herrenschmidt   [PATCH] powerpc: ...
152
  	snprintf(name, sizeof(name), "pmubl");
5474c120a   Michael Hanselmann   [PATCH] Rewritten...
153

a19a6ee6c   Matthew Garrett   backlight: Allow ...
154
  	memset(&props, 0, sizeof(struct backlight_properties));
bb7ca747f   Matthew Garrett   backlight: add ba...
155
  	props.type = BACKLIGHT_PLATFORM;
a19a6ee6c   Matthew Garrett   backlight: Allow ...
156
157
158
  	props.max_brightness = FB_BACKLIGHT_LEVELS - 1;
  	bd = backlight_device_register(name, NULL, NULL, &pmu_backlight_data,
  				       &props);
5474c120a   Michael Hanselmann   [PATCH] Rewritten...
159
  	if (IS_ERR(bd)) {
0094f2cdc   Benjamin Herrenschmidt   [POWERPC] Fix for...
160
161
162
  		printk(KERN_ERR "PMU Backlight registration failed
  ");
  		return;
5474c120a   Michael Hanselmann   [PATCH] Rewritten...
163
  	}
fa19d6348   Benjamin Herrenschmidt   [POWERPC] Fix sle...
164
  	uses_pmu_bl = 1;
d565dd3b0   Benjamin Herrenschmidt   [PATCH] powerpc: ...
165
  	pmu_backlight_init_curve(0x7F, 0x46, 0x0E);
5474c120a   Michael Hanselmann   [PATCH] Rewritten...
166

599a52d12   Richard Purdie   backlight: Separa...
167
  	level = bd->props.max_brightness;
5474c120a   Michael Hanselmann   [PATCH] Rewritten...
168
169
170
171
172
173
  
  	if (autosave) {
  		/* read autosaved value if available */
  		struct adb_request req;
  		pmu_request(&req, NULL, 2, 0xd9, 0);
  		pmu_wait_complete(&req);
d565dd3b0   Benjamin Herrenschmidt   [PATCH] powerpc: ...
174
  		level = pmu_backlight_curve_lookup(
5474c120a   Michael Hanselmann   [PATCH] Rewritten...
175
  				(req.reply[0] >> 4) *
599a52d12   Richard Purdie   backlight: Separa...
176
  				bd->props.max_brightness / 15);
5474c120a   Michael Hanselmann   [PATCH] Rewritten...
177
  	}
599a52d12   Richard Purdie   backlight: Separa...
178
179
  	bd->props.brightness = level;
  	bd->props.power = FB_BLANK_UNBLANK;
28ee086d5   Richard Purdie   backlight: Fix ex...
180
  	backlight_update_status(bd);
5474c120a   Michael Hanselmann   [PATCH] Rewritten...
181

0094f2cdc   Benjamin Herrenschmidt   [POWERPC] Fix for...
182
183
  	printk(KERN_INFO "PMU Backlight initialized (%s)
  ", name);
5474c120a   Michael Hanselmann   [PATCH] Rewritten...
184
  }