1 Index: linux-2.6.24/arch/arm/mach-pxa/spitz.c
2 ===================================================================
3 --- linux-2.6.24.orig/arch/arm/mach-pxa/spitz.c 2008-01-27 02:10:17.000000000 +0000
4 +++ linux-2.6.24/arch/arm/mach-pxa/spitz.c 2008-01-27 02:10:52.000000000 +0000
10 + * Spitz Remote Control Device
12 +static struct platform_device sharpsl_rc_device = {
13 + .name = "sharpsl-remote-control",
27 Index: linux-2.6.24/drivers/input/keyboard/Kconfig
28 ===================================================================
29 --- linux-2.6.24.orig/drivers/input/keyboard/Kconfig 2008-01-27 02:10:20.000000000 +0000
30 +++ linux-2.6.24/drivers/input/keyboard/Kconfig 2008-01-27 02:10:52.000000000 +0000
32 To compile this driver as a module, choose M here: the
33 module will be called spitzkbd.
36 + tristate "Sharp SL-Cxx00 Remote Control"
37 + depends on PXA_SHARPSL
40 + Say Y here to enable the remote on the Sharp Zaurus SL-Cxx00,
41 + SL-C1000, SL-C3000 and Sl-C3100 series of PDAs.
43 + To compile this driver as a module, choose M here: the
44 + module will be called sharpsl_rc.
47 tristate "Amiga keyboard"
49 Index: linux-2.6.24/drivers/input/keyboard/Makefile
50 ===================================================================
51 --- linux-2.6.24.orig/drivers/input/keyboard/Makefile 2008-01-27 02:10:20.000000000 +0000
52 +++ linux-2.6.24/drivers/input/keyboard/Makefile 2008-01-27 02:11:43.000000000 +0000
54 obj-$(CONFIG_KEYBOARD_STOWAWAY) += stowaway.o
55 obj-$(CONFIG_KEYBOARD_CORGI) += corgikbd.o
56 obj-$(CONFIG_KEYBOARD_SPITZ) += spitzkbd.o
57 +obj-$(CONFIG_SHARPSL_RC) += sharpsl_rc.o
58 obj-$(CONFIG_KEYBOARD_ASIC3) += asic3_keys.o
59 obj-$(CONFIG_KEYBOARD_HIL) += hil_kbd.o
60 obj-$(CONFIG_KEYBOARD_HIL_OLD) += hilkbd.o
61 Index: linux-2.6.24/drivers/input/keyboard/sharpsl_rc.c
62 ===================================================================
63 --- /dev/null 1970-01-01 00:00:00.000000000 +0000
64 +++ linux-2.6.24/drivers/input/keyboard/sharpsl_rc.c 2008-01-27 02:10:52.000000000 +0000
67 + * Keyboard driver for Sharp Clamshell Models (SL-Cxx00)
69 + * Copyright (c) 2004-2005 Richard Purdie
71 + * Based on corgikbd.c and Sharp's RC driver
73 + * This program is free software; you can redistribute it and/or modify
74 + * it under the terms of the GNU General Public License version 2 as
75 + * published by the Free Software Foundation.
80 +#include <linux/delay.h>
81 +#include <linux/platform_device.h>
82 +#include <linux/init.h>
83 +#include <linux/input.h>
84 +#include <linux/interrupt.h>
85 +#include <linux/jiffies.h>
86 +#include <linux/module.h>
87 +#include <linux/slab.h>
89 +#ifdef CONFIG_MACH_SPITZ
90 +#include <asm/arch/spitz.h>
92 +#ifdef CONFIG_MACH_CORGI
93 +#include <asm/arch/corgi.h>
96 +#include <asm/arch/hardware.h>
97 +#include <asm/arch/pxa-regs.h>
98 +#include <asm/hardware/scoop.h>
99 +#include <asm/arch/sharpsl.h>
100 +#include <asm/hardware/sharpsl_pm.h>
102 +#define DPRINTK(fmt, args...) dev_dbg(data->dev, fmt "\n", ##args)
104 +struct remote_control_key {
110 +#ifdef CONFIG_MACH_SPITZ
111 +#define REMOTE_AKIN_PULLUP SPITZ_SCP2_AKIN_PULLUP
112 +#define REMOTE_SCOOP_DEVICE spitzscoop2_device
113 +#define REMOTE_GPIO_INT SPITZ_GPIO_AK_INT
114 +#define REMOTE_IRQ_INT SPITZ_IRQ_GPIO_AK_INT
115 +static struct remote_control_key remote_keys[] = {
116 + { 25, 35, KEY_STOPCD},
117 + { 55, 65, KEY_PLAYPAUSE},
118 + { 85, 95, KEY_NEXTSONG},
119 + { 115, 125, KEY_VOLUMEUP},
120 + { 145, 155, KEY_PREVIOUSSONG},
121 + { 180, 190, KEY_MUTE},
122 + { 215, 225, KEY_VOLUMEDOWN},
125 +#ifdef CONFIG_MACH_CORGI
126 +#define REMOTE_AKIN_PULLUP CORGI_SCP_AKIN_PULLUP
127 +#define REMOTE_SCOOP_DEVICE corgiscoop_device
128 +#define REMOTE_GPIO_INT CORGI_GPIO_AK_INT
129 +#define REMOTE_IRQ_INT CORGI_IRQ_GPIO_AK_INT
130 +static struct remote_control_key remote_keys[] = {
131 + //These need to be fixed for the CE-RH1's values
132 + { 25, 35, KEY_STOPCD},
133 + { 55, 65, KEY_PLAYPAUSE},
134 + { 85, 95, KEY_NEXTSONG},
135 + { 115, 125, KEY_VOLUMEUP},
136 + { 145, 155, KEY_PREVIOUSSONG},
137 + { 180, 190, KEY_MUTE},
138 + { 215, 225, KEY_VOLUMEDOWN},
142 +#define RELEASE_HI 230
143 +#define MAX_EARPHONE 6
144 +#define RC_POLL_MS 10
145 +#define RC_FINISH_MS 500
146 +#define WAIT_STATE 3
147 +#define NOISE_THRESHOLD 100
150 + struct input_dev *input;
151 + struct device *dev;
154 + struct timer_list rctimer;
155 + struct timer_list rctimer_finish;
157 + unsigned int handling_press;
158 + unsigned int noise;
159 + unsigned int state;
160 + unsigned int last_key;
163 +static int get_remocon_raw(void)
167 + val = sharpsl_pm_pxa_read_max1111(MAX1111_REMCOM);
168 + for (i = 0; i < ARRAY_SIZE(remote_keys); ++i) {
169 + if (val >= remote_keys[i].min
170 + && val <= remote_keys[i].max) {
171 + printk("get_remocon_raw: VAL=%i, KEY=%i\n", val, remote_keys[i].key);
172 + return remote_keys[i].key;
178 +static irqreturn_t sharpsl_rc_interrupt(int irq, void *dev_id, struct pt_regs *regs)
180 + struct sharpsl_rc *data = dev_id;
181 + DPRINTK("sharpsl_rc_interrupt %d\n", irq);
182 + if (!data->handling_press) {
183 + DPRINTK("handling interrupt");
184 + data->handling_press = 1;
187 + data->last_key = 0;
189 + reset_scoop_gpio(&REMOTE_SCOOP_DEVICE.dev, REMOTE_AKIN_PULLUP);
191 + mod_timer(&data->rctimer, jiffies + msecs_to_jiffies(RC_POLL_MS));
193 + return IRQ_HANDLED;
196 +static void sharpsl_rc_timer_callback(unsigned long dataPtr)
198 + struct sharpsl_rc *data = (struct sharpsl_rc *) dataPtr;
200 + int key = get_remocon_raw();
201 + DPRINTK("timer callback, key: %d", key);
203 + //wait for value to stabilize
204 + if (data->state < WAIT_STATE) {
205 + if (data->last_key != key) {
207 + if (data->noise > NOISE_THRESHOLD) {
208 + DPRINTK("too much noise, bailing");
215 + data->last_key = key;
217 + //stable value, send event
218 + } else if (data->state == WAIT_STATE) {
220 + //non-key returned, skip the rest of the states and bail now
221 + if (data->last_key == 0) {
222 + DPRINTK("non-key detected %d, noise: %d", data->last_key, data->noise);
224 + //send button press
226 + DPRINTK("key press detected %d, noise %d", data->last_key, data->noise);
227 + input_report_key(data->input, data->last_key, 1);
231 + //wait until key is released
232 + } else if (data->state < WAIT_STATE * 2) {
233 + if (key == data->last_key
234 + && data->noise < NOISE_THRESHOLD) {
235 + data->state = WAIT_STATE + 1;
240 + //key is released, send event
242 + //send button release
243 + DPRINTK("release key %d", data->last_key);
244 + input_report_key(data->input, data->last_key, 0);
248 + mod_timer(&data->rctimer, jiffies + msecs_to_jiffies(RC_POLL_MS));
250 + set_scoop_gpio(&REMOTE_SCOOP_DEVICE.dev, REMOTE_AKIN_PULLUP);
251 + data->handling_press = 0;
255 +static int __init sharpsl_rc_probe(struct platform_device *pdev)
257 + struct sharpsl_rc *sharpsl_rc;
258 + struct input_dev *input_dev;
261 + dev_dbg(&pdev->dev, "sharpsl_rc_probe\n");
263 + sharpsl_rc = kzalloc(sizeof(struct sharpsl_rc), GFP_KERNEL);
264 + input_dev = input_allocate_device();
265 + if (!sharpsl_rc || !input_dev) {
267 + input_free_device(input_dev);
271 + platform_set_drvdata(pdev, sharpsl_rc);
273 + sharpsl_rc->dev = &pdev->dev;
274 + sharpsl_rc->input = input_dev;
275 + spin_lock_init(&sharpsl_rc->lock);
277 + /* Init Remote Control Timer */
278 + init_timer(&sharpsl_rc->rctimer);
279 + sharpsl_rc->rctimer.function = sharpsl_rc_timer_callback;
280 + sharpsl_rc->rctimer.data = (unsigned long) sharpsl_rc;
282 + input_dev->name = "Sharp Remote Control CE-RHX";
283 + input_dev->phys = "sharpsl_rc/input0";
284 + input_dev->id.bustype = BUS_HOST;
285 + input_dev->id.vendor = 0x0001;
286 + input_dev->id.product = 0x0001;
287 + input_dev->id.version = 0x0100;
288 + input_dev->cdev.dev = &pdev->dev;
289 + input_dev->private = sharpsl_rc;
291 + input_dev->evbit[0] = BIT(EV_KEY);
293 + for (i = 0; i <= ARRAY_SIZE(remote_keys); i++)
294 + set_bit(remote_keys[i].key, input_dev->keybit);
296 + input_register_device(sharpsl_rc->input);
298 + pxa_gpio_mode(REMOTE_GPIO_INT | GPIO_IN);
299 + ret = request_irq(REMOTE_IRQ_INT,
300 + sharpsl_rc_interrupt,
301 + IRQF_DISABLED | IRQF_TRIGGER_RISING | IRQF_TRIGGER_FALLING | IRQF_SHARED,
305 + dev_dbg(&pdev->dev, "Can't get IRQ: %d!\n", i);
307 + input_free_device(input_dev);
314 +static int sharpsl_rc_remove(struct platform_device *pdev)
316 + struct sharpsl_rc *sharpsl_rc = platform_get_drvdata(pdev);
318 + dev_dbg(&pdev->dev, "sharpsl_rc_remove\n");
320 + free_irq(REMOTE_IRQ_INT, sharpsl_rc);
321 + del_timer_sync(&sharpsl_rc->rctimer);
322 + input_unregister_device(sharpsl_rc->input);
328 +static struct platform_driver sharpsl_rc_driver = {
329 + .probe = sharpsl_rc_probe,
330 + .remove = sharpsl_rc_remove,
334 + .name = "sharpsl-remote-control",
338 +static int __devinit sharpsl_rc_init(void)
340 + printk("sharpsl_rc_init\n");
341 + return platform_driver_register(&sharpsl_rc_driver);
344 +static void __exit sharpsl_rc_exit(void)
346 + printk("sharpsl_rc_exit\n");
347 + platform_driver_unregister(&sharpsl_rc_driver);
350 +module_init(sharpsl_rc_init);
351 +module_exit(sharpsl_rc_exit);
353 +MODULE_AUTHOR("Justin Patrin <papercrane@reversefold.com>");
354 +MODULE_AUTHOR("Richard Purdie <rpurdie@rpsys.net>");
355 +MODULE_DESCRIPTION("SharpSL Remote Control Driver");
356 +MODULE_LICENSE("GPL");
357 Index: linux-2.6.24/drivers/input/keyboard/spitzkbd.c
358 ===================================================================
359 --- linux-2.6.24.orig/drivers/input/keyboard/spitzkbd.c 2008-01-24 22:58:37.000000000 +0000
360 +++ linux-2.6.24/drivers/input/keyboard/spitzkbd.c 2008-01-27 02:10:52.000000000 +0000
362 #include <linux/jiffies.h>
363 #include <linux/module.h>
364 #include <linux/slab.h>
365 +#include <linux/kmod.h>
367 #include <asm/arch/spitz.h>
368 #include <asm/arch/hardware.h>
369 @@ -279,13 +280,21 @@
370 static int sharpsl_hinge_state;
371 static int hinge_count;
373 +void spitzkbd_handle_sharpsl_rc(void *arg) {
374 + request_module("sharpsl_rc");
377 +DECLARE_WORK(spitzkbd_work, spitzkbd_handle_sharpsl_rc);
379 static void spitzkbd_hinge_timer(unsigned long data)
381 struct spitzkbd *spitzkbd_data = (struct spitzkbd *) data;
384 + unsigned int headphone, remote;
386 state = GPLR(SPITZ_GPIO_SWA) & (GPIO_bit(SPITZ_GPIO_SWA)|GPIO_bit(SPITZ_GPIO_SWB));
387 + state |= (GPLR(SPITZ_GPIO_HP_IN) & GPIO_bit(SPITZ_GPIO_HP_IN));
388 state |= (GPLR(SPITZ_GPIO_AK_INT) & GPIO_bit(SPITZ_GPIO_AK_INT));
389 if (state != sharpsl_hinge_state) {
393 input_report_switch(spitzkbd_data->input, SW_LID, ((GPLR(SPITZ_GPIO_SWA) & GPIO_bit(SPITZ_GPIO_SWA)) != 0));
394 input_report_switch(spitzkbd_data->input, SW_TABLET_MODE, ((GPLR(SPITZ_GPIO_SWB) & GPIO_bit(SPITZ_GPIO_SWB)) != 0));
395 - input_report_switch(spitzkbd_data->input, SW_HEADPHONE_INSERT, ((GPLR(SPITZ_GPIO_AK_INT) & GPIO_bit(SPITZ_GPIO_AK_INT)) != 0));
397 + headphone = ((GPLR(SPITZ_GPIO_HP_IN) & GPIO_bit(SPITZ_GPIO_HP_IN)) != 0);
398 + input_report_switch(spitzkbd_data->input, SW_HEADPHONE_INSERT, headphone);
400 + remote = headphone && ((GPLR(SPITZ_GPIO_AK_INT) & GPIO_bit(SPITZ_GPIO_AK_INT)) == 0);
401 + input_report_switch(spitzkbd_data->input, SW_REMOTE_INSERT, remote);
402 input_sync(spitzkbd_data->input);
405 + schedule_work(&spitzkbd_work);
408 spin_unlock_irqrestore(&spitzkbd_data->lock, flags);
410 mod_timer(&spitzkbd_data->htimer, jiffies + msecs_to_jiffies(HINGE_SCAN_INTERVAL));
412 set_bit(SW_LID, input_dev->swbit);
413 set_bit(SW_TABLET_MODE, input_dev->swbit);
414 set_bit(SW_HEADPHONE_INSERT, input_dev->swbit);
415 + set_bit(SW_REMOTE_INSERT, input_dev->swbit);
417 err = input_register_device(input_dev);
420 request_irq(SPITZ_IRQ_GPIO_SWB, spitzkbd_hinge_isr,
421 IRQF_DISABLED | IRQF_TRIGGER_RISING | IRQF_TRIGGER_FALLING,
422 "Spitzkbd SWB", spitzkbd);
423 - request_irq(SPITZ_IRQ_GPIO_AK_INT, spitzkbd_hinge_isr,
424 + request_irq(SPITZ_IRQ_GPIO_HP_IN, spitzkbd_hinge_isr,
425 IRQF_DISABLED | IRQF_TRIGGER_RISING | IRQF_TRIGGER_FALLING,
426 "Spitzkbd HP", spitzkbd);
427 + request_irq(SPITZ_IRQ_GPIO_AK_INT, spitzkbd_hinge_isr,
428 + IRQF_DISABLED | IRQF_TRIGGER_RISING | IRQF_TRIGGER_FALLING | IRQF_SHARED,
429 + "Spitzkbd HP Type", spitzkbd);
434 free_irq(SPITZ_IRQ_GPIO_ON_KEY, spitzkbd);
435 free_irq(SPITZ_IRQ_GPIO_SWA, spitzkbd);
436 free_irq(SPITZ_IRQ_GPIO_SWB, spitzkbd);
437 + free_irq(SPITZ_IRQ_GPIO_HP_IN, spitzkbd);
438 free_irq(SPITZ_IRQ_GPIO_AK_INT, spitzkbd);
440 del_timer_sync(&spitzkbd->htimer);
441 Index: linux-2.6.24/arch/arm/mach-pxa/sharpsl.h
442 ===================================================================
443 --- linux-2.6.24.orig/arch/arm/mach-pxa/sharpsl.h 2008-01-27 02:10:15.000000000 +0000
444 +++ linux-2.6.24/arch/arm/mach-pxa/sharpsl.h 2008-01-27 02:10:52.000000000 +0000
447 #define READ_GPIO_BIT(x) (GPLR(x) & GPIO_bit(x))
449 -/* MAX1111 Channel Definitions */
450 -#define MAX1111_BATT_VOLT 4u
451 -#define MAX1111_BATT_TEMP 2u
452 -#define MAX1111_ACIN_VOLT 6u
454 extern struct battery_thresh spitz_battery_levels_acin[];
455 extern struct battery_thresh spitz_battery_levels_noac[];
456 void sharpsl_pm_pxa_init(void);
457 void sharpsl_pm_pxa_remove(void);
458 -int sharpsl_pm_pxa_read_max1111(int channel);
462 Index: linux-2.6.24/arch/arm/mach-pxa/sharpsl_pm.c
463 ===================================================================
464 --- linux-2.6.24.orig/arch/arm/mach-pxa/sharpsl_pm.c 2008-01-24 22:58:37.000000000 +0000
465 +++ linux-2.6.24/arch/arm/mach-pxa/sharpsl_pm.c 2008-01-27 02:10:52.000000000 +0000
467 | MAXCTRL_SGL | MAXCTRL_UNI | MAXCTRL_STR);
470 +EXPORT_SYMBOL(sharpsl_pm_pxa_read_max1111);
472 void sharpsl_pm_pxa_init(void)
474 pxa_gpio_mode(sharpsl_pm.machinfo->gpio_acin | GPIO_IN);
475 Index: linux-2.6.24/include/asm-arm/hardware/sharpsl_pm.h
476 ===================================================================
477 --- linux-2.6.24.orig/include/asm-arm/hardware/sharpsl_pm.h 2008-01-24 22:58:37.000000000 +0000
478 +++ linux-2.6.24/include/asm-arm/hardware/sharpsl_pm.h 2008-01-27 02:10:52.000000000 +0000
480 irqreturn_t sharpsl_chrg_full_isr(int irq, void *dev_id);
481 irqreturn_t sharpsl_fatal_isr(int irq, void *dev_id);
483 +/* MAX1111 Channel Definitions */
484 +#define MAX1111_REMCOM 0u
485 +#define MAX1111_BATT_VOLT 4u
486 +#define MAX1111_BATT_TEMP 2u
487 +#define MAX1111_ACIN_VOLT 6u
489 +int sharpsl_pm_pxa_read_max1111(int channel);
490 Index: linux-2.6.24/include/linux/input.h
491 ===================================================================
492 --- linux-2.6.24.orig/include/linux/input.h 2008-01-24 22:58:37.000000000 +0000
493 +++ linux-2.6.24/include/linux/input.h 2008-01-27 02:10:52.000000000 +0000
495 #define SW_TABLET_MODE 0x01 /* set = tablet mode */
496 #define SW_HEADPHONE_INSERT 0x02 /* set = inserted */
497 #define SW_RADIO 0x03 /* set = radio enabled */
498 +#define SW_REMOTE_INSERT 0x04 /* set = remote */
500 #define SW_CNT (SW_MAX+1)
502 Index: linux-2.6.24/arch/arm/mach-pxa/spitz_pm.c
503 ===================================================================
504 --- linux-2.6.24.orig/arch/arm/mach-pxa/spitz_pm.c 2008-01-24 22:58:37.000000000 +0000
505 +++ linux-2.6.24/arch/arm/mach-pxa/spitz_pm.c 2008-01-27 02:10:52.000000000 +0000
507 if (resume_on_alarm && (PEDR & PWER_RTC))
508 is_resume |= PWER_RTC;
510 + printk("wakeup: PEDR: %x, PKSR: %x, HP_IN: %x, AK_INT: %x\n", PEDR, PKSR, GPIO_bit(SPITZ_GPIO_HP_IN), GPIO_bit(SPITZ_GPIO_AK_INT));
512 + //remote/headphone interrupt, wakeup
513 + if (PEDR == 0 && (PKSR & 0xc0d01) != 0) {
514 + is_resume |= PWER_RTC;
517 dev_dbg(sharpsl_pm.dev, "is_resume: %x\n",is_resume);