diff options
Diffstat (limited to 'drivers/macintosh')
-rw-r--r-- | drivers/macintosh/Kconfig | 14 | ||||
-rw-r--r-- | drivers/macintosh/adbhid.c | 14 | ||||
-rw-r--r-- | drivers/macintosh/macio_asic.c | 2 | ||||
-rw-r--r-- | drivers/macintosh/smu.c | 53 | ||||
-rw-r--r-- | drivers/macintosh/therm_pm72.c | 218 | ||||
-rw-r--r-- | drivers/macintosh/therm_pm72.h | 33 | ||||
-rw-r--r-- | drivers/macintosh/via-pmu-backlight.c | 121 | ||||
-rw-r--r-- | drivers/macintosh/via-pmu-led.c | 2 | ||||
-rw-r--r-- | drivers/macintosh/via-pmu.c | 51 |
9 files changed, 394 insertions, 114 deletions
diff --git a/drivers/macintosh/Kconfig b/drivers/macintosh/Kconfig index 54f3f6b94efc..d5d649f5ccdb 100644 --- a/drivers/macintosh/Kconfig +++ b/drivers/macintosh/Kconfig | |||
@@ -90,6 +90,15 @@ config ADB_PMU_LED | |||
90 | and the ide-disk LED trigger and configure appropriately through | 90 | and the ide-disk LED trigger and configure appropriately through |
91 | sysfs. | 91 | sysfs. |
92 | 92 | ||
93 | config ADB_PMU_LED_IDE | ||
94 | bool "Use front LED as IDE LED by default" | ||
95 | depends on ADB_PMU_LED | ||
96 | select LEDS_TRIGGERS | ||
97 | select LEDS_TRIGGER_IDE_DISK | ||
98 | help | ||
99 | This option makes the front LED default to the IDE trigger | ||
100 | so that it blinks on IDE activity. | ||
101 | |||
93 | config PMAC_SMU | 102 | config PMAC_SMU |
94 | bool "Support for SMU based PowerMacs" | 103 | bool "Support for SMU based PowerMacs" |
95 | depends on PPC_PMAC64 | 104 | depends on PPC_PMAC64 |
@@ -100,7 +109,7 @@ config PMAC_SMU | |||
100 | 109 | ||
101 | config PMAC_APM_EMU | 110 | config PMAC_APM_EMU |
102 | tristate "APM emulation" | 111 | tristate "APM emulation" |
103 | depends on PPC_PMAC && PPC32 && PM | 112 | depends on PPC_PMAC && PPC32 && PM && ADB_PMU |
104 | 113 | ||
105 | config PMAC_MEDIABAY | 114 | config PMAC_MEDIABAY |
106 | bool "Support PowerBook hotswap media bay" | 115 | bool "Support PowerBook hotswap media bay" |
@@ -113,7 +122,8 @@ config PMAC_MEDIABAY | |||
113 | 122 | ||
114 | config PMAC_BACKLIGHT | 123 | config PMAC_BACKLIGHT |
115 | bool "Backlight control for LCD screens" | 124 | bool "Backlight control for LCD screens" |
116 | depends on ADB_PMU && (BROKEN || !PPC64) | 125 | depends on ADB_PMU && FB = y && (BROKEN || !PPC64) |
126 | select FB_BACKLIGHT | ||
117 | help | 127 | help |
118 | Say Y here to enable Macintosh specific extensions of the generic | 128 | Say Y here to enable Macintosh specific extensions of the generic |
119 | backlight code. With this enabled, the brightness keys on older | 129 | backlight code. With this enabled, the brightness keys on older |
diff --git a/drivers/macintosh/adbhid.c b/drivers/macintosh/adbhid.c index 545be1ed6927..c69d23bb255e 100644 --- a/drivers/macintosh/adbhid.c +++ b/drivers/macintosh/adbhid.c | |||
@@ -45,14 +45,11 @@ | |||
45 | #include <linux/pmu.h> | 45 | #include <linux/pmu.h> |
46 | 46 | ||
47 | #include <asm/machdep.h> | 47 | #include <asm/machdep.h> |
48 | #include <asm/backlight.h> | ||
48 | #ifdef CONFIG_PPC_PMAC | 49 | #ifdef CONFIG_PPC_PMAC |
49 | #include <asm/pmac_feature.h> | 50 | #include <asm/pmac_feature.h> |
50 | #endif | 51 | #endif |
51 | 52 | ||
52 | #ifdef CONFIG_PMAC_BACKLIGHT | ||
53 | #include <asm/backlight.h> | ||
54 | #endif | ||
55 | |||
56 | MODULE_AUTHOR("Franz Sirl <Franz.Sirl-kernel@lauterbach.com>"); | 53 | MODULE_AUTHOR("Franz Sirl <Franz.Sirl-kernel@lauterbach.com>"); |
57 | 54 | ||
58 | #define KEYB_KEYREG 0 /* register # for key up/down data */ | 55 | #define KEYB_KEYREG 0 /* register # for key up/down data */ |
@@ -237,11 +234,6 @@ static struct adb_ids keyboard_ids; | |||
237 | static struct adb_ids mouse_ids; | 234 | static struct adb_ids mouse_ids; |
238 | static struct adb_ids buttons_ids; | 235 | static struct adb_ids buttons_ids; |
239 | 236 | ||
240 | #ifdef CONFIG_PMAC_BACKLIGHT | ||
241 | /* Exported to via-pmu.c */ | ||
242 | int disable_kernel_backlight = 0; | ||
243 | #endif /* CONFIG_PMAC_BACKLIGHT */ | ||
244 | |||
245 | /* Kind of keyboard, see Apple technote 1152 */ | 237 | /* Kind of keyboard, see Apple technote 1152 */ |
246 | #define ADB_KEYBOARD_UNKNOWN 0 | 238 | #define ADB_KEYBOARD_UNKNOWN 0 |
247 | #define ADB_KEYBOARD_ANSI 0x0100 | 239 | #define ADB_KEYBOARD_ANSI 0x0100 |
@@ -527,7 +519,7 @@ adbhid_buttons_input(unsigned char *data, int nb, struct pt_regs *regs, int auto | |||
527 | 519 | ||
528 | case 0xa: /* brightness decrease */ | 520 | case 0xa: /* brightness decrease */ |
529 | #ifdef CONFIG_PMAC_BACKLIGHT | 521 | #ifdef CONFIG_PMAC_BACKLIGHT |
530 | if (!disable_kernel_backlight && down) | 522 | if (down) |
531 | pmac_backlight_key_down(); | 523 | pmac_backlight_key_down(); |
532 | #endif | 524 | #endif |
533 | input_report_key(adbhid[id]->input, KEY_BRIGHTNESSDOWN, down); | 525 | input_report_key(adbhid[id]->input, KEY_BRIGHTNESSDOWN, down); |
@@ -535,7 +527,7 @@ adbhid_buttons_input(unsigned char *data, int nb, struct pt_regs *regs, int auto | |||
535 | 527 | ||
536 | case 0x9: /* brightness increase */ | 528 | case 0x9: /* brightness increase */ |
537 | #ifdef CONFIG_PMAC_BACKLIGHT | 529 | #ifdef CONFIG_PMAC_BACKLIGHT |
538 | if (!disable_kernel_backlight && down) | 530 | if (down) |
539 | pmac_backlight_key_up(); | 531 | pmac_backlight_key_up(); |
540 | #endif | 532 | #endif |
541 | input_report_key(adbhid[id]->input, KEY_BRIGHTNESSUP, down); | 533 | input_report_key(adbhid[id]->input, KEY_BRIGHTNESSUP, down); |
diff --git a/drivers/macintosh/macio_asic.c b/drivers/macintosh/macio_asic.c index 80c0c665b5f6..82657bc86d19 100644 --- a/drivers/macintosh/macio_asic.c +++ b/drivers/macintosh/macio_asic.c | |||
@@ -330,7 +330,7 @@ static void macio_create_fixup_irq(struct macio_dev *dev, int index, | |||
330 | { | 330 | { |
331 | unsigned int irq; | 331 | unsigned int irq; |
332 | 332 | ||
333 | irq = irq_create_mapping(NULL, line, 0); | 333 | irq = irq_create_mapping(NULL, line); |
334 | if (irq != NO_IRQ) { | 334 | if (irq != NO_IRQ) { |
335 | dev->interrupt[index].start = irq; | 335 | dev->interrupt[index].start = irq; |
336 | dev->interrupt[index].flags = IORESOURCE_IRQ; | 336 | dev->interrupt[index].flags = IORESOURCE_IRQ; |
diff --git a/drivers/macintosh/smu.c b/drivers/macintosh/smu.c index f139a74696fe..00ef46898147 100644 --- a/drivers/macintosh/smu.c +++ b/drivers/macintosh/smu.c | |||
@@ -75,9 +75,11 @@ struct smu_device { | |||
75 | struct of_device *of_dev; | 75 | struct of_device *of_dev; |
76 | int doorbell; /* doorbell gpio */ | 76 | int doorbell; /* doorbell gpio */ |
77 | u32 __iomem *db_buf; /* doorbell buffer */ | 77 | u32 __iomem *db_buf; /* doorbell buffer */ |
78 | int db_irq; | 78 | struct device_node *db_node; |
79 | unsigned int db_irq; | ||
79 | int msg; | 80 | int msg; |
80 | int msg_irq; | 81 | struct device_node *msg_node; |
82 | unsigned int msg_irq; | ||
81 | struct smu_cmd_buf *cmd_buf; /* command buffer virtual */ | 83 | struct smu_cmd_buf *cmd_buf; /* command buffer virtual */ |
82 | u32 cmd_buf_abs; /* command buffer absolute */ | 84 | u32 cmd_buf_abs; /* command buffer absolute */ |
83 | struct list_head cmd_list; | 85 | struct list_head cmd_list; |
@@ -93,6 +95,7 @@ struct smu_device { | |||
93 | */ | 95 | */ |
94 | static struct smu_device *smu; | 96 | static struct smu_device *smu; |
95 | static DEFINE_MUTEX(smu_part_access); | 97 | static DEFINE_MUTEX(smu_part_access); |
98 | static int smu_irq_inited; | ||
96 | 99 | ||
97 | static void smu_i2c_retry(unsigned long data); | 100 | static void smu_i2c_retry(unsigned long data); |
98 | 101 | ||
@@ -257,6 +260,10 @@ int smu_queue_cmd(struct smu_cmd *cmd) | |||
257 | smu_start_cmd(); | 260 | smu_start_cmd(); |
258 | spin_unlock_irqrestore(&smu->lock, flags); | 261 | spin_unlock_irqrestore(&smu->lock, flags); |
259 | 262 | ||
263 | /* Workaround for early calls when irq isn't available */ | ||
264 | if (!smu_irq_inited || smu->db_irq == NO_IRQ) | ||
265 | smu_spinwait_cmd(cmd); | ||
266 | |||
260 | return 0; | 267 | return 0; |
261 | } | 268 | } |
262 | EXPORT_SYMBOL(smu_queue_cmd); | 269 | EXPORT_SYMBOL(smu_queue_cmd); |
@@ -478,14 +485,15 @@ int __init smu_init (void) | |||
478 | smu->cmd_buf_abs = (u32)smu_cmdbuf_abs; | 485 | smu->cmd_buf_abs = (u32)smu_cmdbuf_abs; |
479 | smu->cmd_buf = (struct smu_cmd_buf *)abs_to_virt(smu_cmdbuf_abs); | 486 | smu->cmd_buf = (struct smu_cmd_buf *)abs_to_virt(smu_cmdbuf_abs); |
480 | 487 | ||
481 | np = of_find_node_by_name(NULL, "smu-doorbell"); | 488 | smu->db_node = of_find_node_by_name(NULL, "smu-doorbell"); |
482 | if (np == NULL) { | 489 | if (smu->db_node == NULL) { |
483 | printk(KERN_ERR "SMU: Can't find doorbell GPIO !\n"); | 490 | printk(KERN_ERR "SMU: Can't find doorbell GPIO !\n"); |
484 | goto fail; | 491 | goto fail; |
485 | } | 492 | } |
486 | data = (u32 *)get_property(np, "reg", NULL); | 493 | data = (u32 *)get_property(smu->db_node, "reg", NULL); |
487 | if (data == NULL) { | 494 | if (data == NULL) { |
488 | of_node_put(np); | 495 | of_node_put(smu->db_node); |
496 | smu->db_node = NULL; | ||
489 | printk(KERN_ERR "SMU: Can't find doorbell GPIO address !\n"); | 497 | printk(KERN_ERR "SMU: Can't find doorbell GPIO address !\n"); |
490 | goto fail; | 498 | goto fail; |
491 | } | 499 | } |
@@ -497,25 +505,21 @@ int __init smu_init (void) | |||
497 | smu->doorbell = *data; | 505 | smu->doorbell = *data; |
498 | if (smu->doorbell < 0x50) | 506 | if (smu->doorbell < 0x50) |
499 | smu->doorbell += 0x50; | 507 | smu->doorbell += 0x50; |
500 | smu->db_irq = irq_of_parse_and_map(np, 0); | ||
501 | |||
502 | of_node_put(np); | ||
503 | 508 | ||
504 | /* Now look for the smu-interrupt GPIO */ | 509 | /* Now look for the smu-interrupt GPIO */ |
505 | do { | 510 | do { |
506 | np = of_find_node_by_name(NULL, "smu-interrupt"); | 511 | smu->msg_node = of_find_node_by_name(NULL, "smu-interrupt"); |
507 | if (np == NULL) | 512 | if (smu->msg_node == NULL) |
508 | break; | 513 | break; |
509 | data = (u32 *)get_property(np, "reg", NULL); | 514 | data = (u32 *)get_property(smu->msg_node, "reg", NULL); |
510 | if (data == NULL) { | 515 | if (data == NULL) { |
511 | of_node_put(np); | 516 | of_node_put(smu->msg_node); |
517 | smu->msg_node = NULL; | ||
512 | break; | 518 | break; |
513 | } | 519 | } |
514 | smu->msg = *data; | 520 | smu->msg = *data; |
515 | if (smu->msg < 0x50) | 521 | if (smu->msg < 0x50) |
516 | smu->msg += 0x50; | 522 | smu->msg += 0x50; |
517 | smu->msg_irq = irq_of_parse_and_map(np, 0); | ||
518 | of_node_put(np); | ||
519 | } while(0); | 523 | } while(0); |
520 | 524 | ||
521 | /* Doorbell buffer is currently hard-coded, I didn't find a proper | 525 | /* Doorbell buffer is currently hard-coded, I didn't find a proper |
@@ -547,6 +551,19 @@ static int smu_late_init(void) | |||
547 | smu->i2c_timer.function = smu_i2c_retry; | 551 | smu->i2c_timer.function = smu_i2c_retry; |
548 | smu->i2c_timer.data = (unsigned long)smu; | 552 | smu->i2c_timer.data = (unsigned long)smu; |
549 | 553 | ||
554 | if (smu->db_node) { | ||
555 | smu->db_irq = irq_of_parse_and_map(smu->db_node, 0); | ||
556 | if (smu->db_irq == NO_IRQ) | ||
557 | printk(KERN_ERR "smu: failed to map irq for node %s\n", | ||
558 | smu->db_node->full_name); | ||
559 | } | ||
560 | if (smu->msg_node) { | ||
561 | smu->msg_irq = irq_of_parse_and_map(smu->msg_node, 0); | ||
562 | if (smu->msg_irq == NO_IRQ) | ||
563 | printk(KERN_ERR "smu: failed to map irq for node %s\n", | ||
564 | smu->msg_node->full_name); | ||
565 | } | ||
566 | |||
550 | /* | 567 | /* |
551 | * Try to request the interrupts | 568 | * Try to request the interrupts |
552 | */ | 569 | */ |
@@ -571,6 +588,7 @@ static int smu_late_init(void) | |||
571 | } | 588 | } |
572 | } | 589 | } |
573 | 590 | ||
591 | smu_irq_inited = 1; | ||
574 | return 0; | 592 | return 0; |
575 | } | 593 | } |
576 | /* This has to be before arch_initcall as the low i2c stuff relies on the | 594 | /* This has to be before arch_initcall as the low i2c stuff relies on the |
@@ -742,6 +760,11 @@ static void smu_i2c_low_completion(struct smu_cmd *scmd, void *misc) | |||
742 | if (fail && --cmd->retries > 0) { | 760 | if (fail && --cmd->retries > 0) { |
743 | DPRINTK("SMU: i2c failure, starting timer...\n"); | 761 | DPRINTK("SMU: i2c failure, starting timer...\n"); |
744 | BUG_ON(cmd != smu->cmd_i2c_cur); | 762 | BUG_ON(cmd != smu->cmd_i2c_cur); |
763 | if (!smu_irq_inited) { | ||
764 | mdelay(5); | ||
765 | smu_i2c_retry(0); | ||
766 | return; | ||
767 | } | ||
745 | mod_timer(&smu->i2c_timer, jiffies + msecs_to_jiffies(5)); | 768 | mod_timer(&smu->i2c_timer, jiffies + msecs_to_jiffies(5)); |
746 | return; | 769 | return; |
747 | } | 770 | } |
diff --git a/drivers/macintosh/therm_pm72.c b/drivers/macintosh/therm_pm72.c index c1fe0b368f76..20bf67244e2c 100644 --- a/drivers/macintosh/therm_pm72.c +++ b/drivers/macintosh/therm_pm72.c | |||
@@ -95,6 +95,17 @@ | |||
95 | * - Use min/max macros here or there | 95 | * - Use min/max macros here or there |
96 | * - Latest darwin updated U3H min fan speed to 20% PWM | 96 | * - Latest darwin updated U3H min fan speed to 20% PWM |
97 | * | 97 | * |
98 | * July. 06, 2006 : 1.3 | ||
99 | * - Fix setting of RPM fans on Xserve G5 (they were going too fast) | ||
100 | * - Add missing slots fan control loop for Xserve G5 | ||
101 | * - Lower fixed slots fan speed from 50% to 40% on desktop G5s. We | ||
102 | * still can't properly implement the control loop for these, so let's | ||
103 | * reduce the noise a little bit, it appears that 40% still gives us | ||
104 | * a pretty good air flow | ||
105 | * - Add code to "tickle" the FCU regulary so it doesn't think that | ||
106 | * we are gone while in fact, the machine just didn't need any fan | ||
107 | * speed change lately | ||
108 | * | ||
98 | */ | 109 | */ |
99 | 110 | ||
100 | #include <linux/types.h> | 111 | #include <linux/types.h> |
@@ -121,7 +132,7 @@ | |||
121 | 132 | ||
122 | #include "therm_pm72.h" | 133 | #include "therm_pm72.h" |
123 | 134 | ||
124 | #define VERSION "1.2b2" | 135 | #define VERSION "1.3" |
125 | 136 | ||
126 | #undef DEBUG | 137 | #undef DEBUG |
127 | 138 | ||
@@ -146,6 +157,7 @@ static struct basckside_pid_params backside_params; | |||
146 | static struct backside_pid_state backside_state; | 157 | static struct backside_pid_state backside_state; |
147 | static struct drives_pid_state drives_state; | 158 | static struct drives_pid_state drives_state; |
148 | static struct dimm_pid_state dimms_state; | 159 | static struct dimm_pid_state dimms_state; |
160 | static struct slots_pid_state slots_state; | ||
149 | static int state; | 161 | static int state; |
150 | static int cpu_count; | 162 | static int cpu_count; |
151 | static int cpu_pid_type; | 163 | static int cpu_pid_type; |
@@ -154,7 +166,8 @@ static struct completion ctrl_complete; | |||
154 | static int critical_state; | 166 | static int critical_state; |
155 | static int rackmac; | 167 | static int rackmac; |
156 | static s32 dimm_output_clamp; | 168 | static s32 dimm_output_clamp; |
157 | 169 | static int fcu_rpm_shift; | |
170 | static int fcu_tickle_ticks; | ||
158 | static DECLARE_MUTEX(driver_lock); | 171 | static DECLARE_MUTEX(driver_lock); |
159 | 172 | ||
160 | /* | 173 | /* |
@@ -495,13 +508,20 @@ static int start_fcu(void) | |||
495 | rc = fan_write_reg(0x2e, &buf, 1); | 508 | rc = fan_write_reg(0x2e, &buf, 1); |
496 | if (rc < 0) | 509 | if (rc < 0) |
497 | return -EIO; | 510 | return -EIO; |
511 | rc = fan_read_reg(0, &buf, 1); | ||
512 | if (rc < 0) | ||
513 | return -EIO; | ||
514 | fcu_rpm_shift = (buf == 1) ? 2 : 3; | ||
515 | printk(KERN_DEBUG "FCU Initialized, RPM fan shift is %d\n", | ||
516 | fcu_rpm_shift); | ||
517 | |||
498 | return 0; | 518 | return 0; |
499 | } | 519 | } |
500 | 520 | ||
501 | static int set_rpm_fan(int fan_index, int rpm) | 521 | static int set_rpm_fan(int fan_index, int rpm) |
502 | { | 522 | { |
503 | unsigned char buf[2]; | 523 | unsigned char buf[2]; |
504 | int rc, id; | 524 | int rc, id, min, max; |
505 | 525 | ||
506 | if (fcu_fans[fan_index].type != FCU_FAN_RPM) | 526 | if (fcu_fans[fan_index].type != FCU_FAN_RPM) |
507 | return -EINVAL; | 527 | return -EINVAL; |
@@ -509,12 +529,15 @@ static int set_rpm_fan(int fan_index, int rpm) | |||
509 | if (id == FCU_FAN_ABSENT_ID) | 529 | if (id == FCU_FAN_ABSENT_ID) |
510 | return -EINVAL; | 530 | return -EINVAL; |
511 | 531 | ||
512 | if (rpm < 300) | 532 | min = 2400 >> fcu_rpm_shift; |
513 | rpm = 300; | 533 | max = 56000 >> fcu_rpm_shift; |
514 | else if (rpm > 8191) | 534 | |
515 | rpm = 8191; | 535 | if (rpm < min) |
516 | buf[0] = rpm >> 5; | 536 | rpm = min; |
517 | buf[1] = rpm << 3; | 537 | else if (rpm > max) |
538 | rpm = max; | ||
539 | buf[0] = rpm >> (8 - fcu_rpm_shift); | ||
540 | buf[1] = rpm << fcu_rpm_shift; | ||
518 | rc = fan_write_reg(0x10 + (id * 2), buf, 2); | 541 | rc = fan_write_reg(0x10 + (id * 2), buf, 2); |
519 | if (rc < 0) | 542 | if (rc < 0) |
520 | return -EIO; | 543 | return -EIO; |
@@ -551,7 +574,7 @@ static int get_rpm_fan(int fan_index, int programmed) | |||
551 | if (rc != 2) | 574 | if (rc != 2) |
552 | return -EIO; | 575 | return -EIO; |
553 | 576 | ||
554 | return (buf[0] << 5) | buf[1] >> 3; | 577 | return (buf[0] << (8 - fcu_rpm_shift)) | buf[1] >> fcu_rpm_shift; |
555 | } | 578 | } |
556 | 579 | ||
557 | static int set_pwm_fan(int fan_index, int pwm) | 580 | static int set_pwm_fan(int fan_index, int pwm) |
@@ -609,6 +632,26 @@ static int get_pwm_fan(int fan_index) | |||
609 | return (buf[0] * 1000) / 2559; | 632 | return (buf[0] * 1000) / 2559; |
610 | } | 633 | } |
611 | 634 | ||
635 | static void tickle_fcu(void) | ||
636 | { | ||
637 | int pwm; | ||
638 | |||
639 | pwm = get_pwm_fan(SLOTS_FAN_PWM_INDEX); | ||
640 | |||
641 | DBG("FCU Tickle, slots fan is: %d\n", pwm); | ||
642 | if (pwm < 0) | ||
643 | pwm = 100; | ||
644 | |||
645 | if (!rackmac) { | ||
646 | pwm = SLOTS_FAN_DEFAULT_PWM; | ||
647 | } else if (pwm < SLOTS_PID_OUTPUT_MIN) | ||
648 | pwm = SLOTS_PID_OUTPUT_MIN; | ||
649 | |||
650 | /* That is hopefully enough to make the FCU happy */ | ||
651 | set_pwm_fan(SLOTS_FAN_PWM_INDEX, pwm); | ||
652 | } | ||
653 | |||
654 | |||
612 | /* | 655 | /* |
613 | * Utility routine to read the CPU calibration EEPROM data | 656 | * Utility routine to read the CPU calibration EEPROM data |
614 | * from the device-tree | 657 | * from the device-tree |
@@ -715,6 +758,9 @@ BUILD_SHOW_FUNC_INT(backside_fan_pwm, backside_state.pwm) | |||
715 | BUILD_SHOW_FUNC_FIX(drives_temperature, drives_state.last_temp) | 758 | BUILD_SHOW_FUNC_FIX(drives_temperature, drives_state.last_temp) |
716 | BUILD_SHOW_FUNC_INT(drives_fan_rpm, drives_state.rpm) | 759 | BUILD_SHOW_FUNC_INT(drives_fan_rpm, drives_state.rpm) |
717 | 760 | ||
761 | BUILD_SHOW_FUNC_FIX(slots_temperature, slots_state.last_temp) | ||
762 | BUILD_SHOW_FUNC_INT(slots_fan_pwm, slots_state.pwm) | ||
763 | |||
718 | BUILD_SHOW_FUNC_FIX(dimms_temperature, dimms_state.last_temp) | 764 | BUILD_SHOW_FUNC_FIX(dimms_temperature, dimms_state.last_temp) |
719 | 765 | ||
720 | static DEVICE_ATTR(cpu0_temperature,S_IRUGO,show_cpu0_temperature,NULL); | 766 | static DEVICE_ATTR(cpu0_temperature,S_IRUGO,show_cpu0_temperature,NULL); |
@@ -735,6 +781,9 @@ static DEVICE_ATTR(backside_fan_pwm,S_IRUGO,show_backside_fan_pwm,NULL); | |||
735 | static DEVICE_ATTR(drives_temperature,S_IRUGO,show_drives_temperature,NULL); | 781 | static DEVICE_ATTR(drives_temperature,S_IRUGO,show_drives_temperature,NULL); |
736 | static DEVICE_ATTR(drives_fan_rpm,S_IRUGO,show_drives_fan_rpm,NULL); | 782 | static DEVICE_ATTR(drives_fan_rpm,S_IRUGO,show_drives_fan_rpm,NULL); |
737 | 783 | ||
784 | static DEVICE_ATTR(slots_temperature,S_IRUGO,show_slots_temperature,NULL); | ||
785 | static DEVICE_ATTR(slots_fan_pwm,S_IRUGO,show_slots_fan_pwm,NULL); | ||
786 | |||
738 | static DEVICE_ATTR(dimms_temperature,S_IRUGO,show_dimms_temperature,NULL); | 787 | static DEVICE_ATTR(dimms_temperature,S_IRUGO,show_dimms_temperature,NULL); |
739 | 788 | ||
740 | /* | 789 | /* |
@@ -1076,6 +1125,9 @@ static void do_monitor_cpu_rack(struct cpu_pid_state *state) | |||
1076 | fan_min = dimm_output_clamp; | 1125 | fan_min = dimm_output_clamp; |
1077 | fan_min = max(fan_min, (int)state->mpu.rminn_intake_fan); | 1126 | fan_min = max(fan_min, (int)state->mpu.rminn_intake_fan); |
1078 | 1127 | ||
1128 | DBG(" CPU min mpu = %d, min dimm = %d\n", | ||
1129 | state->mpu.rminn_intake_fan, dimm_output_clamp); | ||
1130 | |||
1079 | state->rpm = max(state->rpm, (int)fan_min); | 1131 | state->rpm = max(state->rpm, (int)fan_min); |
1080 | state->rpm = min(state->rpm, (int)state->mpu.rmaxn_intake_fan); | 1132 | state->rpm = min(state->rpm, (int)state->mpu.rmaxn_intake_fan); |
1081 | state->intake_rpm = state->rpm; | 1133 | state->intake_rpm = state->rpm; |
@@ -1374,7 +1426,8 @@ static void do_monitor_drives(struct drives_pid_state *state) | |||
1374 | DBG(" current rpm: %d\n", state->rpm); | 1426 | DBG(" current rpm: %d\n", state->rpm); |
1375 | 1427 | ||
1376 | /* Get some sensor readings */ | 1428 | /* Get some sensor readings */ |
1377 | temp = le16_to_cpu(i2c_smbus_read_word_data(state->monitor, DS1775_TEMP)) << 8; | 1429 | temp = le16_to_cpu(i2c_smbus_read_word_data(state->monitor, |
1430 | DS1775_TEMP)) << 8; | ||
1378 | state->last_temp = temp; | 1431 | state->last_temp = temp; |
1379 | DBG(" temp: %d.%03d, target: %d.%03d\n", FIX32TOPRINT(temp), | 1432 | DBG(" temp: %d.%03d, target: %d.%03d\n", FIX32TOPRINT(temp), |
1380 | FIX32TOPRINT(DRIVES_PID_INPUT_TARGET)); | 1433 | FIX32TOPRINT(DRIVES_PID_INPUT_TARGET)); |
@@ -1575,7 +1628,7 @@ static int init_dimms_state(struct dimm_pid_state *state) | |||
1575 | } | 1628 | } |
1576 | 1629 | ||
1577 | /* | 1630 | /* |
1578 | * Dispose of the state data for the drives control loop | 1631 | * Dispose of the state data for the DIMM control loop |
1579 | */ | 1632 | */ |
1580 | static void dispose_dimms_state(struct dimm_pid_state *state) | 1633 | static void dispose_dimms_state(struct dimm_pid_state *state) |
1581 | { | 1634 | { |
@@ -1588,6 +1641,127 @@ static void dispose_dimms_state(struct dimm_pid_state *state) | |||
1588 | state->monitor = NULL; | 1641 | state->monitor = NULL; |
1589 | } | 1642 | } |
1590 | 1643 | ||
1644 | /* | ||
1645 | * Slots fan control loop | ||
1646 | */ | ||
1647 | static void do_monitor_slots(struct slots_pid_state *state) | ||
1648 | { | ||
1649 | s32 temp, integral, derivative; | ||
1650 | s64 integ_p, deriv_p, prop_p, sum; | ||
1651 | int i, rc; | ||
1652 | |||
1653 | if (--state->ticks != 0) | ||
1654 | return; | ||
1655 | state->ticks = SLOTS_PID_INTERVAL; | ||
1656 | |||
1657 | DBG("slots:\n"); | ||
1658 | |||
1659 | /* Check fan status */ | ||
1660 | rc = get_pwm_fan(SLOTS_FAN_PWM_INDEX); | ||
1661 | if (rc < 0) { | ||
1662 | printk(KERN_WARNING "Error %d reading slots fan !\n", rc); | ||
1663 | /* XXX What do we do now ? */ | ||
1664 | } else | ||
1665 | state->pwm = rc; | ||
1666 | DBG(" current pwm: %d\n", state->pwm); | ||
1667 | |||
1668 | /* Get some sensor readings */ | ||
1669 | temp = le16_to_cpu(i2c_smbus_read_word_data(state->monitor, | ||
1670 | DS1775_TEMP)) << 8; | ||
1671 | state->last_temp = temp; | ||
1672 | DBG(" temp: %d.%03d, target: %d.%03d\n", FIX32TOPRINT(temp), | ||
1673 | FIX32TOPRINT(SLOTS_PID_INPUT_TARGET)); | ||
1674 | |||
1675 | /* Store temperature and error in history array */ | ||
1676 | state->cur_sample = (state->cur_sample + 1) % SLOTS_PID_HISTORY_SIZE; | ||
1677 | state->sample_history[state->cur_sample] = temp; | ||
1678 | state->error_history[state->cur_sample] = temp - SLOTS_PID_INPUT_TARGET; | ||
1679 | |||
1680 | /* If first loop, fill the history table */ | ||
1681 | if (state->first) { | ||
1682 | for (i = 0; i < (SLOTS_PID_HISTORY_SIZE - 1); i++) { | ||
1683 | state->cur_sample = (state->cur_sample + 1) % | ||
1684 | SLOTS_PID_HISTORY_SIZE; | ||
1685 | state->sample_history[state->cur_sample] = temp; | ||
1686 | state->error_history[state->cur_sample] = | ||
1687 | temp - SLOTS_PID_INPUT_TARGET; | ||
1688 | } | ||
1689 | state->first = 0; | ||
1690 | } | ||
1691 | |||
1692 | /* Calculate the integral term */ | ||
1693 | sum = 0; | ||
1694 | integral = 0; | ||
1695 | for (i = 0; i < SLOTS_PID_HISTORY_SIZE; i++) | ||
1696 | integral += state->error_history[i]; | ||
1697 | integral *= SLOTS_PID_INTERVAL; | ||
1698 | DBG(" integral: %08x\n", integral); | ||
1699 | integ_p = ((s64)SLOTS_PID_G_r) * (s64)integral; | ||
1700 | DBG(" integ_p: %d\n", (int)(integ_p >> 36)); | ||
1701 | sum += integ_p; | ||
1702 | |||
1703 | /* Calculate the derivative term */ | ||
1704 | derivative = state->error_history[state->cur_sample] - | ||
1705 | state->error_history[(state->cur_sample + SLOTS_PID_HISTORY_SIZE - 1) | ||
1706 | % SLOTS_PID_HISTORY_SIZE]; | ||
1707 | derivative /= SLOTS_PID_INTERVAL; | ||
1708 | deriv_p = ((s64)SLOTS_PID_G_d) * (s64)derivative; | ||
1709 | DBG(" deriv_p: %d\n", (int)(deriv_p >> 36)); | ||
1710 | sum += deriv_p; | ||
1711 | |||
1712 | /* Calculate the proportional term */ | ||
1713 | prop_p = ((s64)SLOTS_PID_G_p) * (s64)(state->error_history[state->cur_sample]); | ||
1714 | DBG(" prop_p: %d\n", (int)(prop_p >> 36)); | ||
1715 | sum += prop_p; | ||
1716 | |||
1717 | /* Scale sum */ | ||
1718 | sum >>= 36; | ||
1719 | |||
1720 | DBG(" sum: %d\n", (int)sum); | ||
1721 | state->pwm = (s32)sum; | ||
1722 | |||
1723 | state->pwm = max(state->pwm, SLOTS_PID_OUTPUT_MIN); | ||
1724 | state->pwm = min(state->pwm, SLOTS_PID_OUTPUT_MAX); | ||
1725 | |||
1726 | DBG("** DRIVES PWM: %d\n", (int)state->pwm); | ||
1727 | set_pwm_fan(SLOTS_FAN_PWM_INDEX, state->pwm); | ||
1728 | } | ||
1729 | |||
1730 | /* | ||
1731 | * Initialize the state structure for the slots bay fan control loop | ||
1732 | */ | ||
1733 | static int init_slots_state(struct slots_pid_state *state) | ||
1734 | { | ||
1735 | state->ticks = 1; | ||
1736 | state->first = 1; | ||
1737 | state->pwm = 50; | ||
1738 | |||
1739 | state->monitor = attach_i2c_chip(XSERVE_SLOTS_LM75, "slots_temp"); | ||
1740 | if (state->monitor == NULL) | ||
1741 | return -ENODEV; | ||
1742 | |||
1743 | device_create_file(&of_dev->dev, &dev_attr_slots_temperature); | ||
1744 | device_create_file(&of_dev->dev, &dev_attr_slots_fan_pwm); | ||
1745 | |||
1746 | return 0; | ||
1747 | } | ||
1748 | |||
1749 | /* | ||
1750 | * Dispose of the state data for the slots control loop | ||
1751 | */ | ||
1752 | static void dispose_slots_state(struct slots_pid_state *state) | ||
1753 | { | ||
1754 | if (state->monitor == NULL) | ||
1755 | return; | ||
1756 | |||
1757 | device_remove_file(&of_dev->dev, &dev_attr_slots_temperature); | ||
1758 | device_remove_file(&of_dev->dev, &dev_attr_slots_fan_pwm); | ||
1759 | |||
1760 | detach_i2c_chip(state->monitor); | ||
1761 | state->monitor = NULL; | ||
1762 | } | ||
1763 | |||
1764 | |||
1591 | static int call_critical_overtemp(void) | 1765 | static int call_critical_overtemp(void) |
1592 | { | 1766 | { |
1593 | char *argv[] = { critical_overtemp_path, NULL }; | 1767 | char *argv[] = { critical_overtemp_path, NULL }; |
@@ -1617,14 +1791,17 @@ static int main_control_loop(void *x) | |||
1617 | goto out; | 1791 | goto out; |
1618 | } | 1792 | } |
1619 | 1793 | ||
1620 | /* Set the PCI fan once for now */ | 1794 | /* Set the PCI fan once for now on non-RackMac */ |
1621 | set_pwm_fan(SLOTS_FAN_PWM_INDEX, SLOTS_FAN_DEFAULT_PWM); | 1795 | if (!rackmac) |
1796 | set_pwm_fan(SLOTS_FAN_PWM_INDEX, SLOTS_FAN_DEFAULT_PWM); | ||
1622 | 1797 | ||
1623 | /* Initialize ADCs */ | 1798 | /* Initialize ADCs */ |
1624 | initialize_adc(&cpu_state[0]); | 1799 | initialize_adc(&cpu_state[0]); |
1625 | if (cpu_state[1].monitor != NULL) | 1800 | if (cpu_state[1].monitor != NULL) |
1626 | initialize_adc(&cpu_state[1]); | 1801 | initialize_adc(&cpu_state[1]); |
1627 | 1802 | ||
1803 | fcu_tickle_ticks = FCU_TICKLE_TICKS; | ||
1804 | |||
1628 | up(&driver_lock); | 1805 | up(&driver_lock); |
1629 | 1806 | ||
1630 | while (state == state_attached) { | 1807 | while (state == state_attached) { |
@@ -1634,6 +1811,12 @@ static int main_control_loop(void *x) | |||
1634 | 1811 | ||
1635 | down(&driver_lock); | 1812 | down(&driver_lock); |
1636 | 1813 | ||
1814 | /* Tickle the FCU just in case */ | ||
1815 | if (--fcu_tickle_ticks < 0) { | ||
1816 | fcu_tickle_ticks = FCU_TICKLE_TICKS; | ||
1817 | tickle_fcu(); | ||
1818 | } | ||
1819 | |||
1637 | /* First, we always calculate the new DIMMs state on an Xserve */ | 1820 | /* First, we always calculate the new DIMMs state on an Xserve */ |
1638 | if (rackmac) | 1821 | if (rackmac) |
1639 | do_monitor_dimms(&dimms_state); | 1822 | do_monitor_dimms(&dimms_state); |
@@ -1654,7 +1837,9 @@ static int main_control_loop(void *x) | |||
1654 | } | 1837 | } |
1655 | /* Then, the rest */ | 1838 | /* Then, the rest */ |
1656 | do_monitor_backside(&backside_state); | 1839 | do_monitor_backside(&backside_state); |
1657 | if (!rackmac) | 1840 | if (rackmac) |
1841 | do_monitor_slots(&slots_state); | ||
1842 | else | ||
1658 | do_monitor_drives(&drives_state); | 1843 | do_monitor_drives(&drives_state); |
1659 | up(&driver_lock); | 1844 | up(&driver_lock); |
1660 | 1845 | ||
@@ -1696,6 +1881,7 @@ static void dispose_control_loops(void) | |||
1696 | dispose_cpu_state(&cpu_state[1]); | 1881 | dispose_cpu_state(&cpu_state[1]); |
1697 | dispose_backside_state(&backside_state); | 1882 | dispose_backside_state(&backside_state); |
1698 | dispose_drives_state(&drives_state); | 1883 | dispose_drives_state(&drives_state); |
1884 | dispose_slots_state(&slots_state); | ||
1699 | dispose_dimms_state(&dimms_state); | 1885 | dispose_dimms_state(&dimms_state); |
1700 | } | 1886 | } |
1701 | 1887 | ||
@@ -1745,6 +1931,8 @@ static int create_control_loops(void) | |||
1745 | goto fail; | 1931 | goto fail; |
1746 | if (rackmac && init_dimms_state(&dimms_state)) | 1932 | if (rackmac && init_dimms_state(&dimms_state)) |
1747 | goto fail; | 1933 | goto fail; |
1934 | if (rackmac && init_slots_state(&slots_state)) | ||
1935 | goto fail; | ||
1748 | if (!rackmac && init_drives_state(&drives_state)) | 1936 | if (!rackmac && init_drives_state(&drives_state)) |
1749 | goto fail; | 1937 | goto fail; |
1750 | 1938 | ||
diff --git a/drivers/macintosh/therm_pm72.h b/drivers/macintosh/therm_pm72.h index fc7e9b7ecaf2..393cc9df94e1 100644 --- a/drivers/macintosh/therm_pm72.h +++ b/drivers/macintosh/therm_pm72.h | |||
@@ -105,6 +105,7 @@ static char * critical_overtemp_path = "/sbin/critical_overtemp"; | |||
105 | #define DRIVES_DALLAS_ID 0x94 | 105 | #define DRIVES_DALLAS_ID 0x94 |
106 | #define BACKSIDE_MAX_ID 0x98 | 106 | #define BACKSIDE_MAX_ID 0x98 |
107 | #define XSERVE_DIMMS_LM87 0x25a | 107 | #define XSERVE_DIMMS_LM87 0x25a |
108 | #define XSERVE_SLOTS_LM75 0x290 | ||
108 | 109 | ||
109 | /* | 110 | /* |
110 | * Some MAX6690, DS1775, LM87 register definitions | 111 | * Some MAX6690, DS1775, LM87 register definitions |
@@ -198,7 +199,7 @@ struct drives_pid_state | |||
198 | 199 | ||
199 | #define SLOTS_FAN_PWM_DEFAULT_ID 2 | 200 | #define SLOTS_FAN_PWM_DEFAULT_ID 2 |
200 | #define SLOTS_FAN_PWM_INDEX 2 | 201 | #define SLOTS_FAN_PWM_INDEX 2 |
201 | #define SLOTS_FAN_DEFAULT_PWM 50 /* Do better here ! */ | 202 | #define SLOTS_FAN_DEFAULT_PWM 40 /* Do better here ! */ |
202 | 203 | ||
203 | 204 | ||
204 | /* | 205 | /* |
@@ -206,7 +207,7 @@ struct drives_pid_state | |||
206 | */ | 207 | */ |
207 | #define DIMM_PID_G_d 0 | 208 | #define DIMM_PID_G_d 0 |
208 | #define DIMM_PID_G_p 0 | 209 | #define DIMM_PID_G_p 0 |
209 | #define DIMM_PID_G_r 0x6553600 | 210 | #define DIMM_PID_G_r 0x06553600 |
210 | #define DIMM_PID_INPUT_TARGET 3276800 | 211 | #define DIMM_PID_INPUT_TARGET 3276800 |
211 | #define DIMM_PID_INTERVAL 1 | 212 | #define DIMM_PID_INTERVAL 1 |
212 | #define DIMM_PID_OUTPUT_MAX 14000 | 213 | #define DIMM_PID_OUTPUT_MAX 14000 |
@@ -226,6 +227,31 @@ struct dimm_pid_state | |||
226 | }; | 227 | }; |
227 | 228 | ||
228 | 229 | ||
230 | /* | ||
231 | * PID factors for the Xserve Slots control loop | ||
232 | */ | ||
233 | #define SLOTS_PID_G_d 0 | ||
234 | #define SLOTS_PID_G_p 0 | ||
235 | #define SLOTS_PID_G_r 0x00100000 | ||
236 | #define SLOTS_PID_INPUT_TARGET 3200000 | ||
237 | #define SLOTS_PID_INTERVAL 1 | ||
238 | #define SLOTS_PID_OUTPUT_MAX 100 | ||
239 | #define SLOTS_PID_OUTPUT_MIN 20 | ||
240 | #define SLOTS_PID_HISTORY_SIZE 20 | ||
241 | |||
242 | struct slots_pid_state | ||
243 | { | ||
244 | int ticks; | ||
245 | struct i2c_client * monitor; | ||
246 | s32 sample_history[SLOTS_PID_HISTORY_SIZE]; | ||
247 | s32 error_history[SLOTS_PID_HISTORY_SIZE]; | ||
248 | int cur_sample; | ||
249 | s32 last_temp; | ||
250 | int first; | ||
251 | int pwm; | ||
252 | }; | ||
253 | |||
254 | |||
229 | 255 | ||
230 | /* Desktops */ | 256 | /* Desktops */ |
231 | 257 | ||
@@ -283,6 +309,9 @@ struct cpu_pid_state | |||
283 | s32 pump_max; | 309 | s32 pump_max; |
284 | }; | 310 | }; |
285 | 311 | ||
312 | /* Tickle FCU every 10 seconds */ | ||
313 | #define FCU_TICKLE_TICKS 10 | ||
314 | |||
286 | /* | 315 | /* |
287 | * Driver state | 316 | * Driver state |
288 | */ | 317 | */ |
diff --git a/drivers/macintosh/via-pmu-backlight.c b/drivers/macintosh/via-pmu-backlight.c index b42d05f2aaff..a82f313d9dc9 100644 --- a/drivers/macintosh/via-pmu-backlight.c +++ b/drivers/macintosh/via-pmu-backlight.c | |||
@@ -15,19 +15,51 @@ | |||
15 | 15 | ||
16 | #define MAX_PMU_LEVEL 0xFF | 16 | #define MAX_PMU_LEVEL 0xFF |
17 | 17 | ||
18 | static struct device_node *vias; | ||
19 | static struct backlight_properties pmu_backlight_data; | 18 | static struct backlight_properties pmu_backlight_data; |
19 | static spinlock_t pmu_backlight_lock; | ||
20 | static int sleeping; | ||
21 | static u8 bl_curve[FB_BACKLIGHT_LEVELS]; | ||
20 | 22 | ||
21 | static int pmu_backlight_get_level_brightness(struct fb_info *info, | 23 | static void pmu_backlight_init_curve(u8 off, u8 min, u8 max) |
22 | int level) | 24 | { |
25 | unsigned int i, flat, count, range = (max - min); | ||
26 | |||
27 | bl_curve[0] = off; | ||
28 | |||
29 | for (flat = 1; flat < (FB_BACKLIGHT_LEVELS / 16); ++flat) | ||
30 | bl_curve[flat] = min; | ||
31 | |||
32 | count = FB_BACKLIGHT_LEVELS * 15 / 16; | ||
33 | for (i = 0; i < count; ++i) | ||
34 | bl_curve[flat + i] = min + (range * (i + 1) / count); | ||
35 | } | ||
36 | |||
37 | static int pmu_backlight_curve_lookup(int value) | ||
38 | { | ||
39 | int level = (FB_BACKLIGHT_LEVELS - 1); | ||
40 | int i, max = 0; | ||
41 | |||
42 | /* Look for biggest value */ | ||
43 | for (i = 0; i < FB_BACKLIGHT_LEVELS; i++) | ||
44 | max = max((int)bl_curve[i], max); | ||
45 | |||
46 | /* Look for nearest value */ | ||
47 | for (i = 0; i < FB_BACKLIGHT_LEVELS; i++) { | ||
48 | int diff = abs(bl_curve[i] - value); | ||
49 | if (diff < max) { | ||
50 | max = diff; | ||
51 | level = i; | ||
52 | } | ||
53 | } | ||
54 | return level; | ||
55 | } | ||
56 | |||
57 | static int pmu_backlight_get_level_brightness(int level) | ||
23 | { | 58 | { |
24 | int pmulevel; | 59 | int pmulevel; |
25 | 60 | ||
26 | /* Get and convert the value */ | 61 | /* Get and convert the value */ |
27 | mutex_lock(&info->bl_mutex); | 62 | pmulevel = bl_curve[level] * FB_BACKLIGHT_MAX / MAX_PMU_LEVEL; |
28 | pmulevel = info->bl_curve[level] * FB_BACKLIGHT_MAX / MAX_PMU_LEVEL; | ||
29 | mutex_unlock(&info->bl_mutex); | ||
30 | |||
31 | if (pmulevel < 0) | 63 | if (pmulevel < 0) |
32 | pmulevel = 0; | 64 | pmulevel = 0; |
33 | else if (pmulevel > MAX_PMU_LEVEL) | 65 | else if (pmulevel > MAX_PMU_LEVEL) |
@@ -38,25 +70,37 @@ static int pmu_backlight_get_level_brightness(struct fb_info *info, | |||
38 | 70 | ||
39 | static int pmu_backlight_update_status(struct backlight_device *bd) | 71 | static int pmu_backlight_update_status(struct backlight_device *bd) |
40 | { | 72 | { |
41 | struct fb_info *info = class_get_devdata(&bd->class_dev); | ||
42 | struct adb_request req; | 73 | struct adb_request req; |
43 | int pmulevel, level = bd->props->brightness; | 74 | unsigned long flags; |
75 | int level = bd->props->brightness; | ||
76 | |||
77 | spin_lock_irqsave(&pmu_backlight_lock, flags); | ||
44 | 78 | ||
45 | if (vias == NULL) | 79 | /* Don't update brightness when sleeping */ |
46 | return -ENODEV; | 80 | if (sleeping) |
81 | goto out; | ||
47 | 82 | ||
48 | if (bd->props->power != FB_BLANK_UNBLANK || | 83 | if (bd->props->power != FB_BLANK_UNBLANK || |
49 | bd->props->fb_blank != FB_BLANK_UNBLANK) | 84 | bd->props->fb_blank != FB_BLANK_UNBLANK) |
50 | level = 0; | 85 | level = 0; |
51 | 86 | ||
52 | pmulevel = pmu_backlight_get_level_brightness(info, level); | 87 | if (level > 0) { |
88 | int pmulevel = pmu_backlight_get_level_brightness(level); | ||
53 | 89 | ||
54 | pmu_request(&req, NULL, 2, PMU_BACKLIGHT_BRIGHT, pmulevel); | 90 | pmu_request(&req, NULL, 2, PMU_BACKLIGHT_BRIGHT, pmulevel); |
55 | pmu_wait_complete(&req); | 91 | pmu_wait_complete(&req); |
92 | |||
93 | pmu_request(&req, NULL, 2, PMU_POWER_CTRL, | ||
94 | PMU_POW_BACKLIGHT | PMU_POW_ON); | ||
95 | pmu_wait_complete(&req); | ||
96 | } else { | ||
97 | pmu_request(&req, NULL, 2, PMU_POWER_CTRL, | ||
98 | PMU_POW_BACKLIGHT | PMU_POW_OFF); | ||
99 | pmu_wait_complete(&req); | ||
100 | } | ||
56 | 101 | ||
57 | pmu_request(&req, NULL, 2, PMU_POWER_CTRL, | 102 | out: |
58 | PMU_POW_BACKLIGHT | (level > 0 ? PMU_POW_ON : PMU_POW_OFF)); | 103 | spin_unlock_irqrestore(&pmu_backlight_lock, flags); |
59 | pmu_wait_complete(&req); | ||
60 | 104 | ||
61 | return 0; | 105 | return 0; |
62 | } | 106 | } |
@@ -73,15 +117,23 @@ static struct backlight_properties pmu_backlight_data = { | |||
73 | .max_brightness = (FB_BACKLIGHT_LEVELS - 1), | 117 | .max_brightness = (FB_BACKLIGHT_LEVELS - 1), |
74 | }; | 118 | }; |
75 | 119 | ||
76 | void __init pmu_backlight_init(struct device_node *in_vias) | 120 | #ifdef CONFIG_PM |
121 | void pmu_backlight_set_sleep(int sleep) | ||
122 | { | ||
123 | unsigned long flags; | ||
124 | |||
125 | spin_lock_irqsave(&pmu_backlight_lock, flags); | ||
126 | sleeping = sleep; | ||
127 | spin_unlock_irqrestore(&pmu_backlight_lock, flags); | ||
128 | } | ||
129 | #endif /* CONFIG_PM */ | ||
130 | |||
131 | void __init pmu_backlight_init() | ||
77 | { | 132 | { |
78 | struct backlight_device *bd; | 133 | struct backlight_device *bd; |
79 | struct fb_info *info; | ||
80 | char name[10]; | 134 | char name[10]; |
81 | int level, autosave; | 135 | int level, autosave; |
82 | 136 | ||
83 | vias = in_vias; | ||
84 | |||
85 | /* Special case for the old PowerBook since I can't test on it */ | 137 | /* Special case for the old PowerBook since I can't test on it */ |
86 | autosave = | 138 | autosave = |
87 | machine_is_compatible("AAPL,3400/2400") || | 139 | machine_is_compatible("AAPL,3400/2400") || |
@@ -93,27 +145,14 @@ void __init pmu_backlight_init(struct device_node *in_vias) | |||
93 | !machine_is_compatible("PowerBook1,1")) | 145 | !machine_is_compatible("PowerBook1,1")) |
94 | return; | 146 | return; |
95 | 147 | ||
96 | /* Actually, this is a hack, but I don't know of a better way | 148 | snprintf(name, sizeof(name), "pmubl"); |
97 | * to get the first framebuffer device. | ||
98 | */ | ||
99 | info = registered_fb[0]; | ||
100 | if (!info) { | ||
101 | printk("pmubl: No framebuffer found\n"); | ||
102 | goto error; | ||
103 | } | ||
104 | |||
105 | snprintf(name, sizeof(name), "pmubl%d", info->node); | ||
106 | 149 | ||
107 | bd = backlight_device_register(name, info, &pmu_backlight_data); | 150 | bd = backlight_device_register(name, NULL, &pmu_backlight_data); |
108 | if (IS_ERR(bd)) { | 151 | if (IS_ERR(bd)) { |
109 | printk("pmubl: Backlight registration failed\n"); | 152 | printk("pmubl: Backlight registration failed\n"); |
110 | goto error; | 153 | goto error; |
111 | } | 154 | } |
112 | 155 | pmu_backlight_init_curve(0x7F, 0x46, 0x0E); | |
113 | mutex_lock(&info->bl_mutex); | ||
114 | info->bl_dev = bd; | ||
115 | fb_bl_default_curve(info, 0x7F, 0x46, 0x0E); | ||
116 | mutex_unlock(&info->bl_mutex); | ||
117 | 156 | ||
118 | level = pmu_backlight_data.max_brightness; | 157 | level = pmu_backlight_data.max_brightness; |
119 | 158 | ||
@@ -123,18 +162,16 @@ void __init pmu_backlight_init(struct device_node *in_vias) | |||
123 | pmu_request(&req, NULL, 2, 0xd9, 0); | 162 | pmu_request(&req, NULL, 2, 0xd9, 0); |
124 | pmu_wait_complete(&req); | 163 | pmu_wait_complete(&req); |
125 | 164 | ||
126 | mutex_lock(&info->bl_mutex); | 165 | level = pmu_backlight_curve_lookup( |
127 | level = pmac_backlight_curve_lookup(info, | ||
128 | (req.reply[0] >> 4) * | 166 | (req.reply[0] >> 4) * |
129 | pmu_backlight_data.max_brightness / 15); | 167 | pmu_backlight_data.max_brightness / 15); |
130 | mutex_unlock(&info->bl_mutex); | ||
131 | } | 168 | } |
132 | 169 | ||
133 | up(&bd->sem); | 170 | down(&bd->sem); |
134 | bd->props->brightness = level; | 171 | bd->props->brightness = level; |
135 | bd->props->power = FB_BLANK_UNBLANK; | 172 | bd->props->power = FB_BLANK_UNBLANK; |
136 | bd->props->update_status(bd); | 173 | bd->props->update_status(bd); |
137 | down(&bd->sem); | 174 | up(&bd->sem); |
138 | 175 | ||
139 | mutex_lock(&pmac_backlight_mutex); | 176 | mutex_lock(&pmac_backlight_mutex); |
140 | if (!pmac_backlight) | 177 | if (!pmac_backlight) |
diff --git a/drivers/macintosh/via-pmu-led.c b/drivers/macintosh/via-pmu-led.c index af8375ed0f5e..5189d5454b1f 100644 --- a/drivers/macintosh/via-pmu-led.c +++ b/drivers/macintosh/via-pmu-led.c | |||
@@ -74,7 +74,7 @@ static void pmu_led_set(struct led_classdev *led_cdev, | |||
74 | 74 | ||
75 | static struct led_classdev pmu_led = { | 75 | static struct led_classdev pmu_led = { |
76 | .name = "pmu-front-led", | 76 | .name = "pmu-front-led", |
77 | #ifdef CONFIG_BLK_DEV_IDE_PMAC_BLINK | 77 | #ifdef CONFIG_ADB_PMU_LED_IDE |
78 | .default_trigger = "ide-disk", | 78 | .default_trigger = "ide-disk", |
79 | #endif | 79 | #endif |
80 | .brightness_set = pmu_led_set, | 80 | .brightness_set = pmu_led_set, |
diff --git a/drivers/macintosh/via-pmu.c b/drivers/macintosh/via-pmu.c index 06ca80bfd6b9..14610a63f580 100644 --- a/drivers/macintosh/via-pmu.c +++ b/drivers/macintosh/via-pmu.c | |||
@@ -16,7 +16,6 @@ | |||
16 | * a sleep or a freq. switch | 16 | * a sleep or a freq. switch |
17 | * - Move sleep code out of here to pmac_pm, merge into new | 17 | * - Move sleep code out of here to pmac_pm, merge into new |
18 | * common PM infrastructure | 18 | * common PM infrastructure |
19 | * - Move backlight code out as well | ||
20 | * - Save/Restore PCI space properly | 19 | * - Save/Restore PCI space properly |
21 | * | 20 | * |
22 | */ | 21 | */ |
@@ -60,9 +59,7 @@ | |||
60 | #include <asm/mmu_context.h> | 59 | #include <asm/mmu_context.h> |
61 | #include <asm/cputable.h> | 60 | #include <asm/cputable.h> |
62 | #include <asm/time.h> | 61 | #include <asm/time.h> |
63 | #ifdef CONFIG_PMAC_BACKLIGHT | ||
64 | #include <asm/backlight.h> | 62 | #include <asm/backlight.h> |
65 | #endif | ||
66 | 63 | ||
67 | #include "via-pmu-event.h" | 64 | #include "via-pmu-event.h" |
68 | 65 | ||
@@ -177,10 +174,6 @@ static int query_batt_timer = BATTERY_POLLING_COUNT; | |||
177 | static struct adb_request batt_req; | 174 | static struct adb_request batt_req; |
178 | static struct proc_dir_entry *proc_pmu_batt[PMU_MAX_BATTERIES]; | 175 | static struct proc_dir_entry *proc_pmu_batt[PMU_MAX_BATTERIES]; |
179 | 176 | ||
180 | #if defined(CONFIG_INPUT_ADBHID) && defined(CONFIG_PMAC_BACKLIGHT) | ||
181 | extern int disable_kernel_backlight; | ||
182 | #endif /* defined(CONFIG_INPUT_ADBHID) && defined(CONFIG_PMAC_BACKLIGHT) */ | ||
183 | |||
184 | int __fake_sleep; | 177 | int __fake_sleep; |
185 | int asleep; | 178 | int asleep; |
186 | BLOCKING_NOTIFIER_HEAD(sleep_notifier_list); | 179 | BLOCKING_NOTIFIER_HEAD(sleep_notifier_list); |
@@ -466,7 +459,7 @@ static int __init via_pmu_dev_init(void) | |||
466 | 459 | ||
467 | #ifdef CONFIG_PMAC_BACKLIGHT | 460 | #ifdef CONFIG_PMAC_BACKLIGHT |
468 | /* Initialize backlight */ | 461 | /* Initialize backlight */ |
469 | pmu_backlight_init(vias); | 462 | pmu_backlight_init(); |
470 | #endif | 463 | #endif |
471 | 464 | ||
472 | #ifdef CONFIG_PPC32 | 465 | #ifdef CONFIG_PPC32 |
@@ -1403,11 +1396,8 @@ next: | |||
1403 | else if ((1 << pirq) & PMU_INT_SNDBRT) { | 1396 | else if ((1 << pirq) & PMU_INT_SNDBRT) { |
1404 | #ifdef CONFIG_PMAC_BACKLIGHT | 1397 | #ifdef CONFIG_PMAC_BACKLIGHT |
1405 | if (len == 3) | 1398 | if (len == 3) |
1406 | #ifdef CONFIG_INPUT_ADBHID | 1399 | pmac_backlight_set_legacy_brightness_pmu(data[1] >> 4); |
1407 | if (!disable_kernel_backlight) | 1400 | #endif |
1408 | #endif /* CONFIG_INPUT_ADBHID */ | ||
1409 | pmac_backlight_set_legacy_brightness(data[1] >> 4); | ||
1410 | #endif /* CONFIG_PMAC_BACKLIGHT */ | ||
1411 | } | 1401 | } |
1412 | /* Tick interrupt */ | 1402 | /* Tick interrupt */ |
1413 | else if ((1 << pirq) & PMU_INT_TICK) { | 1403 | else if ((1 << pirq) & PMU_INT_TICK) { |
@@ -2005,6 +1995,8 @@ restore_via_state(void) | |||
2005 | out_8(&via[IER], IER_SET | SR_INT | CB1_INT); | 1995 | out_8(&via[IER], IER_SET | SR_INT | CB1_INT); |
2006 | } | 1996 | } |
2007 | 1997 | ||
1998 | extern void pmu_backlight_set_sleep(int sleep); | ||
1999 | |||
2008 | static int | 2000 | static int |
2009 | pmac_suspend_devices(void) | 2001 | pmac_suspend_devices(void) |
2010 | { | 2002 | { |
@@ -2042,6 +2034,11 @@ pmac_suspend_devices(void) | |||
2042 | return -EBUSY; | 2034 | return -EBUSY; |
2043 | } | 2035 | } |
2044 | 2036 | ||
2037 | #ifdef CONFIG_PMAC_BACKLIGHT | ||
2038 | /* Tell backlight code not to muck around with the chip anymore */ | ||
2039 | pmu_backlight_set_sleep(1); | ||
2040 | #endif | ||
2041 | |||
2045 | /* Call platform functions marked "on sleep" */ | 2042 | /* Call platform functions marked "on sleep" */ |
2046 | pmac_pfunc_i2c_suspend(); | 2043 | pmac_pfunc_i2c_suspend(); |
2047 | pmac_pfunc_base_suspend(); | 2044 | pmac_pfunc_base_suspend(); |
@@ -2100,6 +2097,11 @@ pmac_wakeup_devices(void) | |||
2100 | { | 2097 | { |
2101 | mdelay(100); | 2098 | mdelay(100); |
2102 | 2099 | ||
2100 | #ifdef CONFIG_PMAC_BACKLIGHT | ||
2101 | /* Tell backlight code it can use the chip again */ | ||
2102 | pmu_backlight_set_sleep(0); | ||
2103 | #endif | ||
2104 | |||
2103 | /* Power back up system devices (including the PIC) */ | 2105 | /* Power back up system devices (including the PIC) */ |
2104 | device_power_up(); | 2106 | device_power_up(); |
2105 | 2107 | ||
@@ -2414,7 +2416,7 @@ struct pmu_private { | |||
2414 | spinlock_t lock; | 2416 | spinlock_t lock; |
2415 | #if defined(CONFIG_INPUT_ADBHID) && defined(CONFIG_PMAC_BACKLIGHT) | 2417 | #if defined(CONFIG_INPUT_ADBHID) && defined(CONFIG_PMAC_BACKLIGHT) |
2416 | int backlight_locker; | 2418 | int backlight_locker; |
2417 | #endif /* defined(CONFIG_INPUT_ADBHID) && defined(CONFIG_PMAC_BACKLIGHT) */ | 2419 | #endif |
2418 | }; | 2420 | }; |
2419 | 2421 | ||
2420 | static LIST_HEAD(all_pmu_pvt); | 2422 | static LIST_HEAD(all_pmu_pvt); |
@@ -2464,7 +2466,7 @@ pmu_open(struct inode *inode, struct file *file) | |||
2464 | spin_lock_irqsave(&all_pvt_lock, flags); | 2466 | spin_lock_irqsave(&all_pvt_lock, flags); |
2465 | #if defined(CONFIG_INPUT_ADBHID) && defined(CONFIG_PMAC_BACKLIGHT) | 2467 | #if defined(CONFIG_INPUT_ADBHID) && defined(CONFIG_PMAC_BACKLIGHT) |
2466 | pp->backlight_locker = 0; | 2468 | pp->backlight_locker = 0; |
2467 | #endif /* defined(CONFIG_INPUT_ADBHID) && defined(CONFIG_PMAC_BACKLIGHT) */ | 2469 | #endif |
2468 | list_add(&pp->list, &all_pmu_pvt); | 2470 | list_add(&pp->list, &all_pmu_pvt); |
2469 | spin_unlock_irqrestore(&all_pvt_lock, flags); | 2471 | spin_unlock_irqrestore(&all_pvt_lock, flags); |
2470 | file->private_data = pp; | 2472 | file->private_data = pp; |
@@ -2559,13 +2561,12 @@ pmu_release(struct inode *inode, struct file *file) | |||
2559 | spin_lock_irqsave(&all_pvt_lock, flags); | 2561 | spin_lock_irqsave(&all_pvt_lock, flags); |
2560 | list_del(&pp->list); | 2562 | list_del(&pp->list); |
2561 | spin_unlock_irqrestore(&all_pvt_lock, flags); | 2563 | spin_unlock_irqrestore(&all_pvt_lock, flags); |
2564 | |||
2562 | #if defined(CONFIG_INPUT_ADBHID) && defined(CONFIG_PMAC_BACKLIGHT) | 2565 | #if defined(CONFIG_INPUT_ADBHID) && defined(CONFIG_PMAC_BACKLIGHT) |
2563 | if (pp->backlight_locker) { | 2566 | if (pp->backlight_locker) |
2564 | spin_lock_irqsave(&pmu_lock, flags); | 2567 | pmac_backlight_enable(); |
2565 | disable_kernel_backlight--; | 2568 | #endif |
2566 | spin_unlock_irqrestore(&pmu_lock, flags); | 2569 | |
2567 | } | ||
2568 | #endif /* defined(CONFIG_INPUT_ADBHID) && defined(CONFIG_PMAC_BACKLIGHT) */ | ||
2569 | kfree(pp); | 2570 | kfree(pp); |
2570 | } | 2571 | } |
2571 | unlock_kernel(); | 2572 | unlock_kernel(); |
@@ -2642,18 +2643,18 @@ pmu_ioctl(struct inode * inode, struct file *filp, | |||
2642 | #ifdef CONFIG_INPUT_ADBHID | 2643 | #ifdef CONFIG_INPUT_ADBHID |
2643 | case PMU_IOC_GRAB_BACKLIGHT: { | 2644 | case PMU_IOC_GRAB_BACKLIGHT: { |
2644 | struct pmu_private *pp = filp->private_data; | 2645 | struct pmu_private *pp = filp->private_data; |
2645 | unsigned long flags; | ||
2646 | 2646 | ||
2647 | if (pp->backlight_locker) | 2647 | if (pp->backlight_locker) |
2648 | return 0; | 2648 | return 0; |
2649 | |||
2649 | pp->backlight_locker = 1; | 2650 | pp->backlight_locker = 1; |
2650 | spin_lock_irqsave(&pmu_lock, flags); | 2651 | pmac_backlight_disable(); |
2651 | disable_kernel_backlight++; | 2652 | |
2652 | spin_unlock_irqrestore(&pmu_lock, flags); | ||
2653 | return 0; | 2653 | return 0; |
2654 | } | 2654 | } |
2655 | #endif /* CONFIG_INPUT_ADBHID */ | 2655 | #endif /* CONFIG_INPUT_ADBHID */ |
2656 | #endif /* CONFIG_PMAC_BACKLIGHT_LEGACY */ | 2656 | #endif /* CONFIG_PMAC_BACKLIGHT_LEGACY */ |
2657 | |||
2657 | case PMU_IOC_GET_MODEL: | 2658 | case PMU_IOC_GET_MODEL: |
2658 | return put_user(pmu_kind, argp); | 2659 | return put_user(pmu_kind, argp); |
2659 | case PMU_IOC_HAS_ADB: | 2660 | case PMU_IOC_HAS_ADB: |