1 // SPDX-License-Identifier: GPL-2.0
3 * Backlight code for via-pmu
5 * Copyright (C) 1998 Paul Mackerras and Fabio Riccardi.
6 * Copyright (C) 2001-2002 Benjamin Herrenschmidt
7 * Copyright (C) 2006 Michael Hanselmann <linux-kernel@hansmi.ch>
11 #include <asm/ptrace.h>
12 #include <linux/adb.h>
13 #include <linux/pmu.h>
14 #include <asm/backlight.h>
17 #define MAX_PMU_LEVEL 0xFF
19 static const struct backlight_ops pmu_backlight_data
;
20 static DEFINE_SPINLOCK(pmu_backlight_lock
);
21 static int sleeping
, uses_pmu_bl
;
22 static u8 bl_curve
[FB_BACKLIGHT_LEVELS
];
24 static void pmu_backlight_init_curve(u8 off
, u8 min
, u8 max
)
26 int i
, flat
, count
, range
= (max
- min
);
30 for (flat
= 1; flat
< (FB_BACKLIGHT_LEVELS
/ 16); ++flat
)
33 count
= FB_BACKLIGHT_LEVELS
* 15 / 16;
34 for (i
= 0; i
< count
; ++i
)
35 bl_curve
[flat
+ i
] = min
+ (range
* (i
+ 1) / count
);
38 static int pmu_backlight_curve_lookup(int value
)
40 int level
= (FB_BACKLIGHT_LEVELS
- 1);
43 /* Look for biggest value */
44 for (i
= 0; i
< FB_BACKLIGHT_LEVELS
; i
++)
45 max
= max((int)bl_curve
[i
], max
);
47 /* Look for nearest value */
48 for (i
= 0; i
< FB_BACKLIGHT_LEVELS
; i
++) {
49 int diff
= abs(bl_curve
[i
] - value
);
58 static int pmu_backlight_get_level_brightness(int level
)
62 /* Get and convert the value */
63 pmulevel
= bl_curve
[level
] * FB_BACKLIGHT_MAX
/ MAX_PMU_LEVEL
;
66 else if (pmulevel
> MAX_PMU_LEVEL
)
67 pmulevel
= MAX_PMU_LEVEL
;
72 static int __pmu_backlight_update_status(struct backlight_device
*bd
)
74 struct adb_request req
;
75 int level
= bd
->props
.brightness
;
78 if (bd
->props
.power
!= FB_BLANK_UNBLANK
||
79 bd
->props
.fb_blank
!= FB_BLANK_UNBLANK
)
83 int pmulevel
= pmu_backlight_get_level_brightness(level
);
85 pmu_request(&req
, NULL
, 2, PMU_BACKLIGHT_BRIGHT
, pmulevel
);
86 pmu_wait_complete(&req
);
88 pmu_request(&req
, NULL
, 2, PMU_POWER_CTRL
,
89 PMU_POW_BACKLIGHT
| PMU_POW_ON
);
90 pmu_wait_complete(&req
);
92 pmu_request(&req
, NULL
, 2, PMU_POWER_CTRL
,
93 PMU_POW_BACKLIGHT
| PMU_POW_OFF
);
94 pmu_wait_complete(&req
);
100 static int pmu_backlight_update_status(struct backlight_device
*bd
)
105 spin_lock_irqsave(&pmu_backlight_lock
, flags
);
106 /* Don't update brightness when sleeping */
108 rc
= __pmu_backlight_update_status(bd
);
109 spin_unlock_irqrestore(&pmu_backlight_lock
, flags
);
114 static const struct backlight_ops pmu_backlight_data
= {
115 .update_status
= pmu_backlight_update_status
,
120 void pmu_backlight_set_sleep(int sleep
)
124 spin_lock_irqsave(&pmu_backlight_lock
, flags
);
126 if (pmac_backlight
&& uses_pmu_bl
) {
128 struct adb_request req
;
130 pmu_request(&req
, NULL
, 2, PMU_POWER_CTRL
,
131 PMU_POW_BACKLIGHT
| PMU_POW_OFF
);
132 pmu_wait_complete(&req
);
134 __pmu_backlight_update_status(pmac_backlight
);
136 spin_unlock_irqrestore(&pmu_backlight_lock
, flags
);
138 #endif /* CONFIG_PM */
140 void __init
pmu_backlight_init(void)
142 struct backlight_properties props
;
143 struct backlight_device
*bd
;
147 /* Special case for the old PowerBook since I can't test on it */
149 of_machine_is_compatible("AAPL,3400/2400") ||
150 of_machine_is_compatible("AAPL,3500");
153 !pmac_has_backlight_type("pmu") &&
154 !of_machine_is_compatible("AAPL,PowerBook1998") &&
155 !of_machine_is_compatible("PowerBook1,1"))
158 snprintf(name
, sizeof(name
), "pmubl");
160 memset(&props
, 0, sizeof(struct backlight_properties
));
161 props
.type
= BACKLIGHT_PLATFORM
;
162 props
.max_brightness
= FB_BACKLIGHT_LEVELS
- 1;
163 bd
= backlight_device_register(name
, NULL
, NULL
, &pmu_backlight_data
,
166 printk(KERN_ERR
"PMU Backlight registration failed\n");
170 pmu_backlight_init_curve(0x7F, 0x46, 0x0E);
172 level
= bd
->props
.max_brightness
;
175 /* read autosaved value if available */
176 struct adb_request req
;
177 pmu_request(&req
, NULL
, 2, 0xd9, 0);
178 pmu_wait_complete(&req
);
180 level
= pmu_backlight_curve_lookup(
181 (req
.reply
[0] >> 4) *
182 bd
->props
.max_brightness
/ 15);
185 bd
->props
.brightness
= level
;
186 bd
->props
.power
= FB_BLANK_UNBLANK
;
187 backlight_update_status(bd
);
189 printk(KERN_INFO
"PMU Backlight initialized (%s)\n", name
);