ia64/linux-2.6.18-xen.hg

annotate drivers/macintosh/via-pmu-backlight.c @ 893:f994bfe9b93b

linux/blktap2: reduce TLB flush scope

c/s 885 added very coarse TLB flushing. Since these flushes always
follow single page updates, single page flushes (when available) are
sufficient.

Signed-off-by: Jan Beulich <jbeulich@novell.com>
author Keir Fraser <keir.fraser@citrix.com>
date Thu Jun 04 10:32:57 2009 +0100 (2009-06-04)
parents 3e8752eb6d9c
children
rev   line source
ian@0 1 /*
ian@0 2 * Backlight code for via-pmu
ian@0 3 *
ian@0 4 * Copyright (C) 1998 Paul Mackerras and Fabio Riccardi.
ian@0 5 * Copyright (C) 2001-2002 Benjamin Herrenschmidt
ian@0 6 * Copyright (C) 2006 Michael Hanselmann <linux-kernel@hansmi.ch>
ian@0 7 *
ian@0 8 */
ian@0 9
ian@0 10 #include <asm/ptrace.h>
ian@0 11 #include <linux/adb.h>
ian@0 12 #include <linux/pmu.h>
ian@0 13 #include <asm/backlight.h>
ian@0 14 #include <asm/prom.h>
ian@0 15
ian@0 16 #define MAX_PMU_LEVEL 0xFF
ian@0 17
ian@0 18 static struct backlight_properties pmu_backlight_data;
ian@240 19 static DEFINE_SPINLOCK(pmu_backlight_lock);
ian@0 20 static int sleeping;
ian@0 21 static u8 bl_curve[FB_BACKLIGHT_LEVELS];
ian@0 22
ian@0 23 static void pmu_backlight_init_curve(u8 off, u8 min, u8 max)
ian@0 24 {
ian@0 25 unsigned int i, flat, count, range = (max - min);
ian@0 26
ian@0 27 bl_curve[0] = off;
ian@0 28
ian@0 29 for (flat = 1; flat < (FB_BACKLIGHT_LEVELS / 16); ++flat)
ian@0 30 bl_curve[flat] = min;
ian@0 31
ian@0 32 count = FB_BACKLIGHT_LEVELS * 15 / 16;
ian@0 33 for (i = 0; i < count; ++i)
ian@0 34 bl_curve[flat + i] = min + (range * (i + 1) / count);
ian@0 35 }
ian@0 36
ian@0 37 static int pmu_backlight_curve_lookup(int value)
ian@0 38 {
ian@0 39 int level = (FB_BACKLIGHT_LEVELS - 1);
ian@0 40 int i, max = 0;
ian@0 41
ian@0 42 /* Look for biggest value */
ian@0 43 for (i = 0; i < FB_BACKLIGHT_LEVELS; i++)
ian@0 44 max = max((int)bl_curve[i], max);
ian@0 45
ian@0 46 /* Look for nearest value */
ian@0 47 for (i = 0; i < FB_BACKLIGHT_LEVELS; i++) {
ian@0 48 int diff = abs(bl_curve[i] - value);
ian@0 49 if (diff < max) {
ian@0 50 max = diff;
ian@0 51 level = i;
ian@0 52 }
ian@0 53 }
ian@0 54 return level;
ian@0 55 }
ian@0 56
ian@0 57 static int pmu_backlight_get_level_brightness(int level)
ian@0 58 {
ian@0 59 int pmulevel;
ian@0 60
ian@0 61 /* Get and convert the value */
ian@0 62 pmulevel = bl_curve[level] * FB_BACKLIGHT_MAX / MAX_PMU_LEVEL;
ian@0 63 if (pmulevel < 0)
ian@0 64 pmulevel = 0;
ian@0 65 else if (pmulevel > MAX_PMU_LEVEL)
ian@0 66 pmulevel = MAX_PMU_LEVEL;
ian@0 67
ian@0 68 return pmulevel;
ian@0 69 }
ian@0 70
ian@0 71 static int pmu_backlight_update_status(struct backlight_device *bd)
ian@0 72 {
ian@0 73 struct adb_request req;
ian@0 74 unsigned long flags;
ian@0 75 int level = bd->props->brightness;
ian@0 76
ian@0 77 spin_lock_irqsave(&pmu_backlight_lock, flags);
ian@0 78
ian@0 79 /* Don't update brightness when sleeping */
ian@0 80 if (sleeping)
ian@0 81 goto out;
ian@0 82
ian@0 83 if (bd->props->power != FB_BLANK_UNBLANK ||
ian@0 84 bd->props->fb_blank != FB_BLANK_UNBLANK)
ian@0 85 level = 0;
ian@0 86
ian@0 87 if (level > 0) {
ian@0 88 int pmulevel = pmu_backlight_get_level_brightness(level);
ian@0 89
ian@0 90 pmu_request(&req, NULL, 2, PMU_BACKLIGHT_BRIGHT, pmulevel);
ian@0 91 pmu_wait_complete(&req);
ian@0 92
ian@0 93 pmu_request(&req, NULL, 2, PMU_POWER_CTRL,
ian@0 94 PMU_POW_BACKLIGHT | PMU_POW_ON);
ian@0 95 pmu_wait_complete(&req);
ian@0 96 } else {
ian@0 97 pmu_request(&req, NULL, 2, PMU_POWER_CTRL,
ian@0 98 PMU_POW_BACKLIGHT | PMU_POW_OFF);
ian@0 99 pmu_wait_complete(&req);
ian@0 100 }
ian@0 101
ian@0 102 out:
ian@0 103 spin_unlock_irqrestore(&pmu_backlight_lock, flags);
ian@0 104
ian@0 105 return 0;
ian@0 106 }
ian@0 107
ian@0 108 static int pmu_backlight_get_brightness(struct backlight_device *bd)
ian@0 109 {
ian@0 110 return bd->props->brightness;
ian@0 111 }
ian@0 112
ian@0 113 static struct backlight_properties pmu_backlight_data = {
ian@0 114 .owner = THIS_MODULE,
ian@0 115 .get_brightness = pmu_backlight_get_brightness,
ian@0 116 .update_status = pmu_backlight_update_status,
ian@0 117 .max_brightness = (FB_BACKLIGHT_LEVELS - 1),
ian@0 118 };
ian@0 119
ian@0 120 #ifdef CONFIG_PM
ian@0 121 void pmu_backlight_set_sleep(int sleep)
ian@0 122 {
ian@0 123 unsigned long flags;
ian@0 124
ian@0 125 spin_lock_irqsave(&pmu_backlight_lock, flags);
ian@0 126 sleeping = sleep;
ian@0 127 spin_unlock_irqrestore(&pmu_backlight_lock, flags);
ian@0 128 }
ian@0 129 #endif /* CONFIG_PM */
ian@0 130
ian@0 131 void __init pmu_backlight_init()
ian@0 132 {
ian@0 133 struct backlight_device *bd;
ian@0 134 char name[10];
ian@0 135 int level, autosave;
ian@0 136
ian@0 137 /* Special case for the old PowerBook since I can't test on it */
ian@0 138 autosave =
ian@0 139 machine_is_compatible("AAPL,3400/2400") ||
ian@0 140 machine_is_compatible("AAPL,3500");
ian@0 141
ian@0 142 if (!autosave &&
ian@0 143 !pmac_has_backlight_type("pmu") &&
ian@0 144 !machine_is_compatible("AAPL,PowerBook1998") &&
ian@0 145 !machine_is_compatible("PowerBook1,1"))
ian@0 146 return;
ian@0 147
ian@0 148 snprintf(name, sizeof(name), "pmubl");
ian@0 149
ian@0 150 bd = backlight_device_register(name, NULL, &pmu_backlight_data);
ian@0 151 if (IS_ERR(bd)) {
ian@0 152 printk("pmubl: Backlight registration failed\n");
ian@0 153 goto error;
ian@0 154 }
ian@0 155 pmu_backlight_init_curve(0x7F, 0x46, 0x0E);
ian@0 156
ian@0 157 level = pmu_backlight_data.max_brightness;
ian@0 158
ian@0 159 if (autosave) {
ian@0 160 /* read autosaved value if available */
ian@0 161 struct adb_request req;
ian@0 162 pmu_request(&req, NULL, 2, 0xd9, 0);
ian@0 163 pmu_wait_complete(&req);
ian@0 164
ian@0 165 level = pmu_backlight_curve_lookup(
ian@0 166 (req.reply[0] >> 4) *
ian@0 167 pmu_backlight_data.max_brightness / 15);
ian@0 168 }
ian@0 169
ian@0 170 down(&bd->sem);
ian@0 171 bd->props->brightness = level;
ian@0 172 bd->props->power = FB_BLANK_UNBLANK;
ian@0 173 bd->props->update_status(bd);
ian@0 174 up(&bd->sem);
ian@0 175
ian@0 176 mutex_lock(&pmac_backlight_mutex);
ian@0 177 if (!pmac_backlight)
ian@0 178 pmac_backlight = bd;
ian@0 179 mutex_unlock(&pmac_backlight_mutex);
ian@0 180
ian@0 181 printk("pmubl: Backlight initialized (%s)\n", name);
ian@0 182
ian@0 183 return;
ian@0 184
ian@0 185 error:
ian@0 186 return;
ian@0 187 }